自动映射:列出成员

时间:2017-08-10 15:35:17

标签: c# automapper

我希望将任意抽象类型列表映射到共享相同基类型的任意属性集。 这是一些UnitTest代码,目前失败了,我想成功。你能帮助我,获得通用解决方案吗?

以下是课程:

 public class Source
{
    public string Name { get; set; } = "SomeName";
    public Dictionary<string, ValueType> SourceList { get; set; } = new Dictionary<string, ValueType>();
}
public interface IDestination
{
    string Name { get; set; }
}

public class Destination : IDestination     //And many other classes like this, with other properties inherited from ValueType
{
    public string Name { get; set; }

    public double DoubleValue { get; set; }
    public int IntValue { get; set; }

    public string SomeOtherProperty { get; set; }
}

这是单元测试,我想成功:

    [TestMethod]
    public void TestMethod1()
    {
        var source = new Source();
        source.SourceList.Add("IntValue", (int) 3);
        source.SourceList.Add("DoubleValue", (double) 3.14);

        Mapper.Initialize(config =>
        {
            //Put in some magic code here!!!
        });

        var destinationAbstract = Mapper.Map<Source, IDestination>(source);     //the type of destination is known only at runtime. Therefore Mapping to Interface

        var destination = (Destination) destinationAbstract;
        Assert.AreEqual(source.Name, destination.Name);
        Assert.AreEqual((int)source.SourceList["IntValue"], destination.IntValue);
        Assert.AreEqual((double)source.SourceList["DoubleValue"], destination.DoubleValue);
    }

请注意,

  • 从IDestination继承的类数仅在运行时
  • 每个Source-instance的SourceList内容可能不同,因此每个类定义的目标类属性也可能会发生变化

我希望你能帮助我,因为我无法在文档的帮助下确定通用解决方案。

提前致谢。

2 个答案:

答案 0 :(得分:0)

默认情况下,您可以从Dictionary<string, object>(属性名称到属性值)映射到某个类,而无需任何额外配置。 docstests

答案 1 :(得分:0)

在考虑了Lucians的暗示后,在使用Automapper尝试不同的事情后,我终于找到了一个初始单元测试的解决方案:

    [TestMethod]
    public void TestMethod1()
    {
        var source = new Source();
        source.SourceList.Add("IntValue", (int) 3);
        source.SourceList.Add("DoubleValue", (double) 3.14);

        Mapper.Initialize(config =>
        {
            //"Magic code"
            config.CreateMap<Source, IDestination>();
            config.CreateMap(typeof(Source), typeof(Destination)).IncludeBase(typeof(Source), typeof(IDestination));
        });

        //standard map-call
        var destination = Mapper.Map<Destination>(source);
        //Additional "Trick":
        Dictionary<string, object> mappingDict =
            source.SourceList.ToDictionary(pair => pair.Key, pair => (object) pair.Value);
        Mapper.Map(mappingDict, destination, typeof(Dictionary<string, object>), typeof(Destination));

        Assert.AreEqual(source.Name, destination.Name);
        Assert.AreEqual(source.SourceList["IntValue"], destination.IntValue);
        Assert.AreEqual(source.SourceList["DoubleValue"], destination.DoubleValue);
    }

&#34;技巧&#34;是将Dictionary<string, ValueType>转换为Dictionary<string,object>并将此字典成员映射到目标对象(!)到标准map-call。 这有效,但有一些缺点:

  1. 无法进行映射验证(验证说明:源成员&#34; SourceList&#34;未映射或目标成员&#34; DoubleValue&#34;或&#34; IntValue&#34;未映射)
  2. 施放字典有点难看(对我来说似乎没必要......)
  3. 我需要2次调用Mapper.Map而不是只调用一次。
  4. 在我看来,没有其他方法可以解决我最初的问题。但我愿意接受我的解决方案的任何建议或改进。 通过使用反射也可以轻松解决最初的问题,因此应该存在适当的映射设置的所有信息,但是我无法找到这种正确的映射设置。