Skip to content

Commit

Permalink
added support for deserialization of dictionaries with complex types.
Browse files Browse the repository at this point in the history
  • Loading branch information
craiggwilson committed May 16, 2010
1 parent b33bccb commit 5004bf4
Show file tree
Hide file tree
Showing 12 changed files with 127 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -131,11 +131,9 @@ public void CanSerializeGenericDictionary()
}

[Test]
public void CanSerializeAndDeserializeGenericDictionarys()
public void CanDeserializeGenericDictionary()
{
var expectedBson = Serialize<Document>(new Document("Property", new Document() { { "key1", 10 }, { "key2", 20 } }));
var obj = new GenericDictionary{Property = new Dictionary<string, int> { { "key1", 10 }, { "key2", 20 } }};
var bson = Serialize<GenericDictionary>(obj);
var bson = Serialize<Document>(new Document("Property", new Document() { { "key1", 10 }, { "key2", 20 } }));
var prop = Deserialize<GenericDictionary>(bson);

Assert.IsNotNull(prop);
Expand All @@ -145,6 +143,38 @@ public void CanSerializeAndDeserializeGenericDictionarys()
Assert.Contains(new KeyValuePair<string, int>("key2", 20), prop.Property);
}

public class GenericDictionaryWithComplexType
{
public Dictionary<string, GenericDictionaryComplexType> Property { get; set; }
}

public class GenericDictionaryComplexType
{
public string Name { get; set; }
}

[Test]
public void CanSerializeGenericDictionaryWithComplexType()
{
var expectedBson = Serialize<Document>(new Document("Property", new Document() { { "key1", new Document("Name", "a") }, { "key2", new Document("Name", "b") } }));
var obj = new GenericDictionaryWithComplexType { Property = new Dictionary<string, GenericDictionaryComplexType> { { "key1", new GenericDictionaryComplexType() { Name = "a" } }, { "key2", new GenericDictionaryComplexType() { Name = "b" } } } };
var bson = Serialize<GenericDictionaryWithComplexType>(obj);
Assert.AreEqual(expectedBson, bson);
}

[Test]
public void CanDeserializeGenericDictionaryWithComplexType()
{
var bson = Serialize<Document>(new Document("Property", new Document() { { "key1", new Document("Name", "a") }, { "key2", new Document("Name", "b") } }));
var prop = Deserialize<GenericDictionaryWithComplexType>(bson);

Assert.IsNotNull(prop);
Assert.IsNotNull(prop.Property);
Assert.AreEqual(2, prop.Property.Count);
Assert.IsTrue(prop.Property["key1"].Name == "a");
Assert.IsTrue(prop.Property["key2"].Name == "b");
}

public class HashSetHelper
{
public HashSet<string> Property { get; set; }
Expand Down
2 changes: 2 additions & 0 deletions source/MongoDB/MongoDB.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,8 @@
<Compile Include="MapReduce.cs" />
<Compile Include="Commands\MapReduceCommand.cs" />
<Compile Include="Results\MapReduceResult.cs" />
<Compile Include="Serialization\Builders\DictionaryBuilder.cs" />
<Compile Include="Serialization\Builders\PropertyDescriptor.cs" />
<Compile Include="Serialization\Descriptors\DictionaryPropertyDescriptor.cs" />
<Compile Include="Util\ScopedDictionary.cs" />
<Compile Include="Linq\Translators\AggregateChecker.cs" />
Expand Down
16 changes: 15 additions & 1 deletion source/MongoDB/Serialization/BsonClassMapBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ namespace MongoDB.Serialization
{
internal class BsonClassMapBuilder : IBsonObjectBuilder
{
private bool _isDictionary;
private readonly Stack<Type> _types;
private readonly IMappingStore _mappingStore;

Expand All @@ -21,6 +22,12 @@ public BsonClassMapBuilder(IMappingStore mappingStore, Type classType)

public object BeginObject()
{
if (_isDictionary)
{
_isDictionary = false;
return new DictionaryBuilder(_types.Peek());
}

if (_types.Peek() == null || _types.Peek() == typeof(Document))
return new DocumentBuilder();

Expand Down Expand Up @@ -51,7 +58,14 @@ public object EndArray(object instance)

public void BeginProperty(object instance, string name)
{
_types.Push(((IObjectBuilder)instance).GetPropertyType(name));
var propDescriptor = ((IObjectBuilder)instance).GetPropertyDescriptor(name);
if (propDescriptor == null)
_types.Push(null);
else
{
_types.Push(propDescriptor.Type);
_isDictionary = propDescriptor.IsDictionary;
}
}

public void EndProperty(object instance, string name, object value)
Expand Down
4 changes: 2 additions & 2 deletions source/MongoDB/Serialization/Builders/ArrayBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@ private object GetTypedList()
/// </summary>
/// <param name="name">The name.</param>
/// <returns></returns>
public Type GetPropertyType(string name)
public PropertyDescriptor GetPropertyDescriptor(string name)
{
return _elementType;
return new PropertyDescriptor() { Type = _elementType };
}

/// <summary>
Expand Down
13 changes: 9 additions & 4 deletions source/MongoDB/Serialization/Builders/ConcreteClassMapBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,23 @@ public object BuildObject()
return _instance;
}

public Type GetPropertyType(string name)
public PropertyDescriptor GetPropertyDescriptor(string name)
{
var memberMap = _classMap.GetMemberMapFromAlias(name);
if (memberMap == null)
return null;

var type = memberMap.MemberReturnType;
bool isDictionary = false;
if (memberMap is CollectionMemberMap)
return ((CollectionMemberMap)memberMap).ElementType;
type = ((CollectionMemberMap)memberMap).ElementType;
else if (memberMap is DictionaryMemberMap)
return ((DictionaryMemberMap)memberMap).ValueType;
{
type = ((DictionaryMemberMap)memberMap).ValueType;
isDictionary = true;
}

return memberMap.MemberReturnType;
return new PropertyDescriptor() { Type = type, IsDictionary = isDictionary };
}
}
}
34 changes: 34 additions & 0 deletions source/MongoDB/Serialization/Builders/DictionaryBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MongoDB.Serialization.Builders
{
public class DictionaryBuilder : IObjectBuilder
{
private Document _document;
private Type _valueType;

public DictionaryBuilder(Type valueType)
{
_document = new Document();
_valueType = valueType;
}

public void AddProperty(string name, object value)
{
_document.Add(name, value);
}

public object BuildObject()
{
return _document;
}

public PropertyDescriptor GetPropertyDescriptor(string name)
{
return new PropertyDescriptor() { Type = _valueType, IsDictionary = false };
}
}
}
4 changes: 2 additions & 2 deletions source/MongoDB/Serialization/Builders/DocumentBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ public object BuildObject()
/// </summary>
/// <param name="name">The name.</param>
/// <returns></returns>
public Type GetPropertyType(string name)
public PropertyDescriptor GetPropertyDescriptor(string name)
{
return null;
return new PropertyDescriptor();
}
}
}
2 changes: 1 addition & 1 deletion source/MongoDB/Serialization/Builders/IObjectBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ internal interface IObjectBuilder

object BuildObject();

Type GetPropertyType(string name);
PropertyDescriptor GetPropertyDescriptor(string name);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,23 @@ public object BuildObject()
return _concreteEntityBuilder.BuildObject();
}

public Type GetPropertyType(string name)
public PropertyDescriptor GetPropertyDescriptor(string name)
{
var memberMap = _classMap.GetMemberMapFromAlias(name);
if (memberMap == null)
return null;

var type = memberMap.MemberReturnType;
bool isDictionary = false;
if (memberMap is CollectionMemberMap)
return ((CollectionMemberMap)memberMap).ElementType;
type = ((CollectionMemberMap)memberMap).ElementType;
else if (memberMap is DictionaryMemberMap)
{
type = ((DictionaryMemberMap)memberMap).ValueType;
isDictionary = true;
}

return memberMap.MemberReturnType;
return new PropertyDescriptor() { Type = type, IsDictionary = isDictionary };
}
}
}
14 changes: 14 additions & 0 deletions source/MongoDB/Serialization/Builders/PropertyDescriptor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MongoDB.Serialization.Builders
{
public class PropertyDescriptor
{
public Type Type { get; set; }

public bool IsDictionary { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public override IEnumerable<BsonProperty> GetProperties()
/// <returns></returns>
private BsonPropertyValue GetValue(PropertyInfo propertyInfo)
{
Type type;
Type type = null;
var value = propertyInfo.GetValue(_example, null);
if (value != null && typeof(Code).IsAssignableFrom(value.GetType()))
{
Expand All @@ -61,14 +61,16 @@ private BsonPropertyValue GetValue(PropertyInfo propertyInfo)
var memberMap = GetMemberMapFromMemberName(propertyInfo.Name);
if (memberMap != null)
{
type = memberMap.MemberReturnType;
if (memberMap is CollectionMemberMap)
type = ((CollectionMemberMap)memberMap).ElementType;
else if (memberMap is DictionaryMemberMap)
{
type = ((DictionaryMemberMap)memberMap).ValueType;
isDictionary = true;
}

if (type == null || type == typeof(object))
type = memberMap.MemberReturnType;
}
else
type = propertyInfo.PropertyType;
Expand Down
Empty file.

0 comments on commit 5004bf4

Please sign in to comment.