[go: nahoru, domu]

Skip to content

Commit

Permalink
Multilevel mappers, with discriminators in middle classes, and suppor…
Browse files Browse the repository at this point in the history
…t to abstract and non-abstract middle classes.
  • Loading branch information
masbicudo committed May 9, 2016
1 parent 4692870 commit db97e45
Show file tree
Hide file tree
Showing 18 changed files with 592 additions and 85 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,11 @@
<Compile Include="JsonMapBase.cs" />
<Compile Include="JsonMapExtensions.cs" />
<Compile Include="JsonMaps.cs" />
<Compile Include="JsonMapsCache.cs" />
<Compile Include="JsonMapsContractResolver.cs" />
<Compile Include="JsonMapsConverter.cs" />
<Compile Include="JsonMapsTree.cs" />
<Compile Include="JsonMapsTreeNode.cs" />
<Compile Include="JsonSubclassMap.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Utils\EnumExt.cs" />
Expand Down
11 changes: 11 additions & 0 deletions Fluent-Json.NET-Configuration/JsonMap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,5 +90,16 @@ T IAndSubtypes<T>.CreateObject(string discriminatorValue)

public abstract class JsonMap : JsonMapBase
{
public override object CreateNew()
{
return Activator.CreateInstance(this.SerializedType);
}

public override bool CanCreateNew()
{
return !this.SerializedType.IsAbstract
&& !this.SerializedType.IsInterface
&& (this.SerializedType.IsValueType || this.SerializedType.GetConstructor(new Type[0]) != null);
}
}
}
4 changes: 4 additions & 0 deletions Fluent-Json.NET-Configuration/JsonMapBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,9 @@ protected void DiscriminateSubClassesOnField(string fieldName)
{
this.DiscriminatorFieldName = fieldName;
}

public abstract object CreateNew();

public abstract bool CanCreateNew();
}
}
8 changes: 8 additions & 0 deletions Fluent-Json.NET-Configuration/JsonMapsCache.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace FluentJsonNet
{
public class JsonMapsCache
{
public JsonMapBase[] Mappers { get; set; }
public JsonMapBase[][] SubMappers { get; set; }
}
}
279 changes: 204 additions & 75 deletions Fluent-Json.NET-Configuration/JsonMapsConverter.cs

Large diffs are not rendered by default.

85 changes: 85 additions & 0 deletions Fluent-Json.NET-Configuration/JsonMapsTree.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
using System;
using System.Collections.Generic;
using System.Linq;

namespace FluentJsonNet
{
public class JsonMapsTree
{
private readonly Dictionary<Type, JsonMapsTreeNode> dictionary;

public JsonMapsTree(Dictionary<Type, JsonMapsTreeNode> dictionary)
{
this.dictionary = dictionary;
}

public IEnumerable<JsonMapBase> GetMappers(Type objectType)
{
// find mapper in the dictionary
var current = objectType;
while (current != null)
{
int count = 0;
JsonMapsTreeNode node;
if (this.dictionary.TryGetValue(current, out node))
count++;

var nodes = this.dictionary
.Where(kv => kv.Value.Mapper is IAndSubtypes)
.Where(kv => kv.Value != node)
.Where(kv => kv.Value.Mapper.AcceptsType(current))
.Select(kv => kv.Value)
.ToList();

count += nodes.Count;

if (count > 1)
throw new Exception($"Ambiguous maps for the type `{current.Name}`");

if (nodes.Count > 0)
node = nodes[0];

if (node == null)
yield break;

yield return node.Mapper;

if (node.Mapper is JsonMap)
yield break;

current = current.BaseType;
}
}

public IEnumerable<JsonMapBase[]> GetSubpathes(Type objectType)
{
JsonMapsTreeNode rootNode;
if (!this.dictionary.TryGetValue(objectType, out rootNode) || rootNode.Children.Count == 0)
yield break;

var list = new Stack<JsonMapBase>(20);
var stack = new Stack<Queue<JsonMapsTreeNode>>(20);
var node = rootNode;
stack.Push(new Queue<JsonMapsTreeNode>(node.Children.Select(ct => this.dictionary[ct])));
while (true)
{
var currentLevel = stack.Peek();
if (currentLevel.Count > 0)
{
node = currentLevel.Dequeue();
stack.Push(new Queue<JsonMapsTreeNode>(node.Children.Select(ct => this.dictionary[ct])));
list.Push(node.Mapper);
}
else
{
stack.Pop();
if (stack.Count == 0)
yield break;
if (list.Peek().CanCreateNew())
yield return list.ToArray();
list.Pop();
}
}
}
}
}
20 changes: 20 additions & 0 deletions Fluent-Json.NET-Configuration/JsonMapsTreeNode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;

namespace FluentJsonNet
{
public class JsonMapsTreeNode
{
public JsonMapsTreeNode(JsonMapBase mapper, Type parent, Type[] children)
{
this.Mapper = mapper;
this.Parent = parent;
this.Children = new ReadOnlyCollection<Type>(children);
}

public JsonMapBase Mapper { get; }
public Type Parent { get; }
public IReadOnlyCollection<Type> Children { get; }
}
}
9 changes: 8 additions & 1 deletion Fluent-Json.NET-Configuration/JsonSubclassMap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,16 @@ protected void DiscriminatorValue(string fieldValue)
this.DiscriminatorFieldValue = fieldValue;
}

public virtual object CreateNew()
public override object CreateNew()
{
return Activator.CreateInstance(this.SerializedType);
}

public override bool CanCreateNew()
{
return !this.SerializedType.IsAbstract
&& !this.SerializedType.IsInterface
&& (this.SerializedType.IsValueType || this.SerializedType.GetConstructor(new Type[0]) != null);
}
}
}
1 change: 1 addition & 0 deletions FluentJsonNetTests/FluentJsonNetTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@
<Compile Include="Models\Cat.cs" />
<Compile Include="Models\Lion.cs" />
<Compile Include="MyAssert.cs" />
<Compile Include="NonDefaultTestMapperAttribute.cs" />
<Compile Include="UnitTest1.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="UnitTestBase.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

namespace FluentJsonNetTests.Maps.Controls
{
[NonDefaultTestMapper]
public class ControlModelMapBaseDiscriminator : JsonMap<ControlModel>
{
public ControlModelMapBaseDiscriminator()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

namespace FluentJsonNetTests.Maps.Controls
{
[NonDefaultTestMapper]
public class EditorModelMapDoubleDiscriminator : JsonSubclassMap<EditorModel>
{
public EditorModelMapDoubleDiscriminator()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

namespace FluentJsonNetTests.Maps.Controls
{
[NonDefaultTestMapper]
public class EditorModelMapNoDiscriminator : JsonSubclassMap<EditorModel>
{
public EditorModelMapNoDiscriminator()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

namespace FluentJsonNetTests.Maps.Controls
{
[NonDefaultTestMapper]
public class TextBoxModelMapNoDiscriminator : JsonSubclassMap<TextBoxModel>
{
public TextBoxModelMapNoDiscriminator()
Expand Down
2 changes: 1 addition & 1 deletion FluentJsonNetTests/Maps/CatMap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace FluentJsonNetTests.Maps
{
public class CatMap : JsonMap<Cat>
public class CatMap : JsonSubclassMap<Cat>
{
public CatMap()
{
Expand Down
2 changes: 1 addition & 1 deletion FluentJsonNetTests/Maps/GiraffeMap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace FluentJsonNetTests.Maps
{
public class GiraffeMap : JsonMap<Giraffe>
public class GiraffeMap : JsonSubclassMap<Giraffe>
{
public GiraffeMap()
{
Expand Down
12 changes: 12 additions & 0 deletions FluentJsonNetTests/NonDefaultTestMapperAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System;

namespace FluentJsonNetTests
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
sealed class NonDefaultTestMapperAttribute : Attribute
{
public NonDefaultTestMapperAttribute()
{
}
}
}
Loading

0 comments on commit db97e45

Please sign in to comment.