【问题标题】:Mapping dictionaries with AutoMapper使用 AutoMapper 映射字典
【发布时间】:2011-08-25 02:36:00
【问题描述】:

鉴于这些类,我如何映射它们的字典?

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

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


Mapper.CreateMap<TestClass, TestClassDto>();
Mapper.CreateMap<Dictionary<string, TestClass>, 
                  Dictionary<string, TestClassDto>>();

var testDict = new Dictionary<string, TestClass>();
var testValue = new TestClass() {Name = "value1"};
testDict.Add("key1", testValue);

var mappedValue = Mapper.Map<TestClass, TestClassDto>(testValue);

var mappedDict = Mapper.Map<Dictionary<string, TestClass>, 
                            Dictionary<string, TestClassDto>>(testDict);

映射其中一个,在本例中为 mappedValue,工作正常。

映射它们的字典最终在目标对象中没有条目。

我在做什么?

【问题讨论】:

    标签: automapper


    【解决方案1】:

    AutoMapper 发生了一些变化,看起来更像:

    CreateMap<Thing, ThingDto>()
         .ReverseMap();
    CreateMap<Thing, KeyValuePair<int, ThingDto>>()
         .ConstructUsing((t, ctx) => new KeyValuePair<int, ThingDto>(t.id, ctx.Mapper.Map<ThingDto>(t)));
    

    【讨论】:

    • 查看@oflahero 的评论。
    • 他的评论和其他任何人的评论都引用了当前版本的 ConstructUsing,它将两个参数传递给 func (t,ctx),其中 t 是 ThingDto 类型,ctx 是 ResolutionContext。 TMappingExpression ConstructUsing(Func ctor)
    • @LucianBargaoanu 我希望我在浪费一两个小时试图获得原始解决方案和评论工作之前阅读 Skychan 的答案。非常相关
    • 其实这比手动映射还差。这是混淆的手动映射。它完全违背了 AM 的目的。所以说真的,你要么学会正确使用 AM,要么自己动手。
    • @LucianBargaoanu 请帮助我们了解在这种情况下我们可以使用 AM 的替代方式。您可能有一点,我们应该只使用手动映射而不是这个,我会记住这一点。我很好奇您是否知道另一种正确使用 AM 来完成这种情况的方法。映射字典一定是一个很常见的东西,在这里学习我们都会受益。
    【解决方案2】:

    您遇到的问题是因为 AutoMapper 正在努力映射字典的 内容。您必须考虑它是存储什么的 - 在本例中为 KeyValuePairs

    如果您尝试为 KeyValuePair 组合创建映射器,您将很快发现您不能直接使用,因为 Key 属性没有设置器

    AutoMapper 通过允许您使用构造函数映射来解决这个问题。

    /* Create the map for the base object - be explicit for good readability */
    Mapper.CreateMap<TestClass, TestClassDto>()
          .ForMember( x => x.Name, o => o.MapFrom( y => y.Name ) );
    
    /* Create the map using construct using rather than ForMember */
    Mapper.CreateMap<KeyValuePair<string, TestClass>, KeyValuePair<string, TestClassDto>>()
          .ConstructUsing( x => new KeyValuePair<string, TestClassDto>( x.Key, 
                                                                        x.Value.MapTo<TestClassDto>() ) );
    
    var testDict = new Dictionary<string, TestClass>();
    var testValue = new TestClass()
    {
        Name = "value1"
    };
    testDict.Add( "key1", testValue );
    
    /* Mapped Dict will have your new KeyValuePair in there */
    var mappedDict = Mapper.Map<Dictionary<string, TestClass>,
    Dictionary<string, TestClassDto>>( testDict );
    

    【讨论】:

    • 请注意,第二个 ConstructUsing 位使用第一个映射来完成它的工作。
    • 在我的测试用例中,即使在添加CreateMap&lt;KeyValuePair&lt;string, TestClass&gt;, KeyValuePair&lt;string, TestClassDto&gt;&gt;() 之后不使用ConstructUsing,它也开始工作
    • 甜蜜,在过去的 7 年里可能发生了变化 :)
    • 你甚至不需要 KeyValuePair 映射(至少在当前版本中不需要)——事实上,你不需要 Dictionary -> DIctionary 映射根本 .只需 TestClass->TestClassDTO 即可。它是显式的 Dictionary->DIctionary 映射,导致一个空的 DIctionary。 AutoMapper 隐式支持封闭的泛型类型映射。 (是的,我知道这个问题已经超过七年了;))
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-09
    相关资源
    最近更新 更多