Skip to content

Commit

Permalink
serialization of dictionaries works.
Browse files Browse the repository at this point in the history
  • Loading branch information
craiggwilson committed May 15, 2010
1 parent 810ea69 commit b33bccb
Show file tree
Hide file tree
Showing 21 changed files with 163 additions and 128 deletions.
Expand Up @@ -121,9 +121,19 @@ public class GenericDictionary
public Dictionary<string, int> Property { get; set; }
}

[Test]
public void CanSerializeGenericDictionary()
{
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);
Assert.AreEqual(expectedBson, bson);
}

[Test]
public void CanSerializeAndDeserializeGenericDictionarys()
{
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 prop = Deserialize<GenericDictionary>(bson);
Expand Down
Expand Up @@ -8,23 +8,26 @@ namespace MongoDB.Configuration.DictionaryAdapters
{
public class DocumentDictionaryAdapter : IDictionaryAdapter
{
public object CreateDictionary(Type valueType, DictionaryEntry[] pairs)
/// <summary>
/// Creates the dictionary.
/// </summary>
/// <param name="valueType">Type of the value.</param>
/// <param name="document">The document.</param>
/// <returns></returns>
public object CreateDictionary(Type valueType, Document document)
{
var doc = new Document();

foreach (var pair in pairs)
doc.Add((string)pair.Key, pair.Value);

return doc;
return document;
}

public IEnumerable<DictionaryEntry> GetPairs(object collection)
/// <summary>
/// Gets the pairs.
/// </summary>
/// <param name="dictionary">The collection.</param>
/// <param name="valueType">Type of the value.</param>
/// <returns></returns>
public Document GetDocument(object dictionary, Type valueType)
{
var doc = collection as Document;
if (doc == null)
return Enumerable.Empty<DictionaryEntry>();

return doc.Select(x => new DictionaryEntry(x.Key, x.Value));
return dictionary as Document;
}
}
}
Expand Up @@ -15,14 +15,14 @@ public class GenericDictionaryDictionaryAdapter : IDictionaryAdapter
/// Creates the dictionary.
/// </summary>
/// <param name="valueType">Type of the value.</param>
/// <param name="pairs">The pairs.</param>
/// <param name="document">The document.</param>
/// <returns></returns>
public object CreateDictionary(Type valueType, DictionaryEntry[] pairs)
public object CreateDictionary(Type valueType, Document document)
{
var closedType = OpenType.MakeGenericType(typeof(string), valueType);
var instance = Activator.CreateInstance(closedType);
var addMethod = closedType.GetMethod("Add", new [] { typeof(string), valueType });
foreach(var pair in pairs)
foreach (var pair in document)
addMethod.Invoke(instance, new [] {pair.Key, pair.Value });

return instance;
Expand All @@ -31,11 +31,19 @@ public object CreateDictionary(Type valueType, DictionaryEntry[] pairs)
/// <summary>
/// Gets the pairs.
/// </summary>
/// <param name="collection">The collection.</param>
/// <param name="dictionary">The collection.</param>
/// <returns></returns>
public IEnumerable<DictionaryEntry> GetPairs(object collection)
public Document GetDocument(object dictionary, Type valueType)
{
throw new NotImplementedException();
var type = typeof(KeyValuePair<,>).MakeGenericType(typeof(string), valueType);
var keyProperty = type.GetProperty("Key");
var valueProperty = type.GetProperty("Value");

var doc = new Document();
foreach (object e in (IEnumerable)dictionary)
doc.Add(keyProperty.GetValue(e, null).ToString(), valueProperty.GetValue(e, null));

return doc;
}
}
}
Expand Up @@ -8,23 +8,39 @@ namespace MongoDB.Configuration.DictionaryAdapters
{
public class HashtableDictionaryAdapter : IDictionaryAdapter
{
public object CreateDictionary(Type valueType, DictionaryEntry[] pairs)
/// <summary>
/// Creates the dictionary.
/// </summary>
/// <param name="valueType">Type of the value.</param>
/// <param name="document">The document.</param>
/// <returns></returns>
public object CreateDictionary(Type valueType, Document document)
{
var hashtable = new Hashtable();

foreach (var pair in pairs)
foreach (var pair in document)
hashtable.Add((string)pair.Key, pair.Value);

return hashtable;
}

public IEnumerable<DictionaryEntry> GetPairs(object collection)
/// <summary>
/// Gets the document.
/// </summary>
/// <param name="collection">The collection.</param>
/// <param name="valueType">Type of the value.</param>
/// <returns></returns>
public Document GetDocument(object collection, Type valueType)
{
var hashtable = collection as Hashtable;
if (hashtable == null)
return Enumerable.Empty<DictionaryEntry>();
return new Document();

return hashtable.OfType<DictionaryEntry>();
var doc = new Document();
foreach (DictionaryEntry entry in hashtable)
doc.Add(entry.Key.ToString(), entry.Value);

return doc;
}
}
}
Expand Up @@ -13,15 +13,16 @@ public interface IDictionaryAdapter
/// Creates the dictionary.
/// </summary>
/// <param name="valueType">Type of the value.</param>
/// <param name="pairs">The pairs.</param>
/// <param name="document">The document.</param>
/// <returns></returns>
object CreateDictionary(Type valueType, DictionaryEntry[] pairs);
object CreateDictionary(Type valueType, Document document);

/// <summary>
/// Gets the pairs.
/// Gets the document.
/// </summary>
/// <param name="collection">The collection.</param>
/// <param name="dictionary">The dictionary.</param>
/// <param name="valueType">Type of the value.</param>
/// <returns></returns>
IEnumerable<DictionaryEntry> GetPairs(object collection);
Document GetDocument(object dictionary, Type valueType);
}
}
Expand Up @@ -30,6 +30,7 @@ public class DefaultCollectionAdapterConvention : ICollectionAdapterConvention
{ typeof(IList), CreateArrayListCollectionType },
{ typeof(ICollection), CreateArrayListCollectionType },
{ typeof(IEnumerable), CreateArrayListCollectionType },
{ typeof(HashSet<>), CreateGenericSetCollectionType },
{ typeof(List<>), CreateGenericListCollectionType },
{ typeof(IList<>), CreateGenericListCollectionType },
{ typeof(ICollection<>), CreateGenericListCollectionType },
Expand All @@ -47,6 +48,7 @@ public class DefaultCollectionAdapterConvention : ICollectionAdapterConvention
{ typeof(IList), GetArrayListElementType },
{ typeof(ICollection), GetArrayListElementType },
{ typeof(IEnumerable), GetArrayListElementType },
{ typeof(HashSet<>), GetGenericSetElementType },
{ typeof(List<>), GetGenericListElementType },
{ typeof(IList<>), GetGenericListElementType },
{ typeof(ICollection<>), GetGenericListElementType },
Expand Down Expand Up @@ -127,5 +129,15 @@ private static Type GetGenericListElementType(Type type)
{
return type.GetGenericArguments()[0];
}

private static GenericSetCollectionAdapter CreateGenericSetCollectionType()
{
return new GenericSetCollectionAdapter();
}

private static Type GetGenericSetElementType(Type type)
{
return type.GetGenericArguments()[0];
}
}
}
Expand Up @@ -122,7 +122,6 @@ private static IDictionaryAdapter CreateGenericDictionaryType()

private static Type GetGenericDictionaryValueType(Type type)
{
type = type.GetGenericTypeDefinition();
return type.GetGenericArguments()[1];
}
}
Expand Down
@@ -1,6 +1,9 @@
using System;
using MongoDB.Configuration.DictionaryAdapters;
using System.Collections;
using System.Linq;

using MongoDB.Configuration.DictionaryAdapters;


namespace MongoDB.Configuration.Mapping.Model
{
Expand Down Expand Up @@ -39,7 +42,8 @@ public DictionaryMemberMap(string memberName, Func<object, object> getter, Actio
/// <returns></returns>
public override object GetValue(object instance)
{
return base.GetValue(_dictionaryAdapter.GetPairs(instance));
var value = base.GetValue(instance);
return _dictionaryAdapter.GetDocument(value, _valueType);
}

/// <summary>
Expand All @@ -49,7 +53,7 @@ public override object GetValue(object instance)
/// <param name="value">The value.</param>
public override void SetValue(object instance, object value)
{
base.SetValue(instance, _dictionaryAdapter.CreateDictionary(_valueType, (DictionaryEntry[])value));
base.SetValue(instance, _dictionaryAdapter.CreateDictionary(_valueType, (Document)value));
}
}
}
2 changes: 1 addition & 1 deletion source/MongoDB/MongoDB.csproj
Expand Up @@ -141,7 +141,7 @@
<Compile Include="MapReduce.cs" />
<Compile Include="Commands\MapReduceCommand.cs" />
<Compile Include="Results\MapReduceResult.cs" />
<Compile Include="Serialization\Builders\DictionaryBuilder.cs" />
<Compile Include="Serialization\Descriptors\DictionaryPropertyDescriptor.cs" />
<Compile Include="Util\ScopedDictionary.cs" />
<Compile Include="Linq\Translators\AggregateChecker.cs" />
<Compile Include="Linq\Translators\AggregateRewriter.cs" />
Expand Down
3 changes: 0 additions & 3 deletions source/MongoDB/Serialization/BsonClassMapBuilder.cs
Expand Up @@ -41,9 +41,6 @@ public object EndObject(object instance)

public object BeginArray()
{
if(typeof(IDictionary).IsAssignableFrom(_types.Peek()))
return new DictionaryBuilder(_types.Peek());

return new ArrayBuilder(_types.Peek());
}

Expand Down
14 changes: 9 additions & 5 deletions source/MongoDB/Serialization/BsonClassMapDescriptor.cs
Expand Up @@ -11,6 +11,7 @@ internal class BsonClassMapDescriptor : IBsonObjectDescriptor
{
private readonly Stack<Type> _types;
private readonly IMappingStore _mappingStore;
private bool _isDictionaryProperty;

public BsonClassMapDescriptor(IMappingStore mappingStore, Type rootType)
{
Expand All @@ -19,6 +20,7 @@ public BsonClassMapDescriptor(IMappingStore mappingStore, Type rootType)
if (rootType == null)
throw new ArgumentNullException("rootType");

_isDictionaryProperty = false;
_mappingStore = mappingStore;
_types = new Stack<Type>();
_types.Push(rootType);
Expand All @@ -44,7 +46,6 @@ public object BeginArray(object instance)
{
return new ArrayDescriptor((IEnumerable)instance, _types.Peek());
}

public IEnumerable<BsonProperty> GetProperties(object instance)
{
return ((IPropertyDescriptor)instance).GetProperties();
Expand All @@ -55,7 +56,8 @@ public void BeginProperty(object instance, BsonProperty property)
var value = property.Value as BsonPropertyValue;
if (value == null)
return;


_isDictionaryProperty = value.IsDictionary;
_types.Push(value.Type);
property.Value = value.Value;
}
Expand Down Expand Up @@ -86,14 +88,16 @@ public bool IsObject(object instance)

private object BeginDocument(Document document)
{
if (_isDictionaryProperty)
{
_isDictionaryProperty = false;
return new DictionaryPropertyDescriptor(document, _types.Peek());
}
if (typeof(Document).IsAssignableFrom(_types.Peek()))
return new DocumentPropertyDescriptor(document);

var currentClassMap = _mappingStore.GetClassMap(_types.Peek());

//var doc = (Document)instance;
//if (doc.ContainsKey("mapreduce"))
// _isMapReduce = true;
return new DocumentClassMapPropertyDescriptor(_mappingStore, currentClassMap, document);
}

Expand Down
Expand Up @@ -48,6 +48,8 @@ public Type GetPropertyType(string name)

if (memberMap is CollectionMemberMap)
return ((CollectionMemberMap)memberMap).ElementType;
else if (memberMap is DictionaryMemberMap)
return ((DictionaryMemberMap)memberMap).ValueType;

return memberMap.MemberReturnType;
}
Expand Down
67 changes: 0 additions & 67 deletions source/MongoDB/Serialization/Builders/DictionaryBuilder.cs

This file was deleted.

0 comments on commit b33bccb

Please sign in to comment.