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.
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
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
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
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
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
@@ -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
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
Expand Up @@ -8,6 +8,6 @@ internal interface IObjectBuilder

object BuildObject();

Type GetPropertyType(string name);
PropertyDescriptor GetPropertyDescriptor(string name);
}
}
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
@@ -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; }
}
}
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.