Skip to content

Commit

Permalink
Made DictionaryAdapter compatible with any type of key
Browse files Browse the repository at this point in the history
  • Loading branch information
sven-n committed Aug 30, 2018
1 parent 845efa4 commit 4cb67da
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 3 deletions.
85 changes: 85 additions & 0 deletions src/Mapster.Tests/WhenMappingWithDictionary.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Shouldly;

Expand Down Expand Up @@ -213,6 +215,64 @@ public void Dictionary_Of_String_Mix()
result["_b"].ShouldBe(2);
}

[TestMethod]
public void AdaptClassWithIntegerKeyDictionary()
{
TypeAdapterConfig<ClassWithIntKeyDictionary, OtherClassWithIntKeyDictionary>.NewConfig();
TypeAdapterConfig<Dictionary<int, SimplePoco>, Dictionary<int, SimplePoco>>.NewConfig();

var instanceWithDictionary = new ClassWithIntKeyDictionary();
instanceWithDictionary.Dict = new Dictionary<int, SimplePoco>
{
{ 1 , new SimplePoco { Id = Guid.NewGuid(), Name = "one"} },
{ 100 , new SimplePoco { Id = Guid.NewGuid(), Name = "one hundred"} },
};

var result = instanceWithDictionary.Adapt<OtherClassWithIntKeyDictionary>();
result.Dict.ShouldContainKey(1);
result.Dict.ShouldContainKey(100);
result.Dict[1].Name.ShouldBe("one");
result.Dict[100].Name.ShouldBe("one hundred");
}

[TestMethod]
public void AdaptClassWithIntegerKeyDictionaryInterface()
{
TypeAdapterConfig<ClassWithIntKeyIDictionary, ClassWithIntKeyIDictionary>.NewConfig();
TypeAdapterConfig<Dictionary<int, SimplePoco>, Dictionary<int, SimplePoco>>.NewConfig();
TypeAdapterConfig.GlobalSettings.ForDestinationType<IDictionary<int, SimplePoco>>().ConstructUsing(() => new Dictionary<int, SimplePoco>());

var instanceWithDictionary = new ClassWithIntKeyDictionary();
instanceWithDictionary.Dict = new Dictionary<int, SimplePoco>
{
{ 1 , new SimplePoco { Id = Guid.NewGuid(), Name = "one"} },
{ 100 , new SimplePoco { Id = Guid.NewGuid(), Name = "one hundred"} },
};

var result = instanceWithDictionary.Adapt<ClassWithIntKeyIDictionary>();
result.Dict.ShouldContainKey(1);
result.Dict.ShouldContainKey(100);
result.Dict[1].Name.ShouldBe("one");
result.Dict[100].Name.ShouldBe("one hundred");
}

[TestMethod]
public void AdaptClassWithObjectKeyDictionary()
{
TypeAdapterConfig<ClassWithPocoKeyDictionary, OtherClassWithPocoKeyDictionary>.NewConfig();
TypeAdapterConfig<Dictionary<SimplePoco, int>, Dictionary<SimplePoco, int>>.NewConfig();
var instanceWithDictionary = new ClassWithPocoKeyDictionary();
instanceWithDictionary.Dict = new Dictionary<SimplePoco, int>
{
{ new SimplePoco { Id = Guid.NewGuid(), Name = "one"}, 1 },
{ new SimplePoco { Id = Guid.NewGuid(), Name = "one hundred"}, 100 },
};

var result = instanceWithDictionary.Adapt<OtherClassWithPocoKeyDictionary>();
result.Dict.Keys.Any(k => k.Name == "one").ShouldBeTrue();
result.Dict.Keys.Any(k => k.Name == "one hundred").ShouldBeTrue();
}

public class SimplePoco
{
public Guid Id { get; set; }
Expand All @@ -223,5 +283,30 @@ public class A
{
public Dictionary<int, decimal> Prop { get; set; }
}

public class ClassWithIntKeyDictionary
{
public Dictionary<int, SimplePoco> Dict { get; set; }
}

public class ClassWithIntKeyIDictionary
{
public IDictionary<int, SimplePoco> Dict { get; set; }
}

public class OtherClassWithIntKeyDictionary
{
public Dictionary<int, SimplePoco> Dict { get; set; }
}

public class ClassWithPocoKeyDictionary
{
public Dictionary<SimplePoco, int> Dict { get; set; }
}

public class OtherClassWithPocoKeyDictionary
{
public Dictionary<SimplePoco, int> Dict { get; set; }
}
}
}
8 changes: 5 additions & 3 deletions src/Mapster/Adapters/DictionaryAdapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ internal class DictionaryAdapter : ClassAdapter
protected override bool CanMap(PreCompileArgument arg)
{
var dictType = arg.DestinationType.GetDictionaryType();
return dictType?.GetGenericArguments()[0] == typeof (string);
return dictType != null;
}

protected override bool CanInline(Expression source, Expression destination, CompileArgument arg)
Expand All @@ -37,9 +37,10 @@ protected override Expression CreateBlockExpression(Expression source, Expressio
if (srcDictType == null || arg.Settings.IgnoreNonMapped == true)
return mapped;

var keyType = srcDictType.GetGenericArguments().First();
var kvpType = source.Type.ExtractCollectionType();
var kvp = Expression.Variable(kvpType, "kvp");
var key = Expression.Variable(typeof(string), "key");
var key = Expression.Variable(keyType, "key");
var keyAssign = Expression.Assign(key, Expression.Property(kvp, "Key"));

//dest[kvp.Key] = convert(kvp.Value);
Expand Down Expand Up @@ -141,8 +142,9 @@ protected override Expression CreateInlineExpression(Expression source, CompileA
var members = classConverter.Members;

var dictType = arg.DestinationType.GetDictionaryType();
var keyType = dictType.GetGenericArguments()[0];
var valueType = dictType.GetGenericArguments()[1];
var add = dictType.GetMethod("Add", new[] { typeof(string), valueType });
var add = dictType.GetMethod("Add", new[] { keyType, valueType });

var lines = new List<ElementInit>();
if (listInit != null)
Expand Down

0 comments on commit 4cb67da

Please sign in to comment.