AutoMapper将未映射的属性映射到Dictionary / ExtensionData

Mar*_*der 4 .net c# automapper-5

如何使AutoMapper将缺少的未映射属性映射到目标对象内的字典?(类似于序列化期间的ExtensionData

例:

class Source
{
    public int A {get;set;} 
    public int B {get;set;} 
    public int C {get;set;} 
}

class Destination
{
    public int A {get;set;}
    public Dictionary<string, object> D {get;set;}
}

Source s = new Source { A = 1, B = 2, C = 3 };
Destination d = ... // Mapping code
Run Code Online (Sandbox Code Playgroud)

现在我想要以下结果:

d.A ==> 1
d.D ==> {{ "B", 2 }, { "C", 3 }}
Run Code Online (Sandbox Code Playgroud)

*编辑*

最后,我正在寻找一种无反射的解决方案。含义:在设置/配置/初始化期间允许反射,但是在映射本身期间,我不希望反射引起任何延迟。

*编辑*

我正在寻找一种通用的解决方案,就像序列化程序一样。

Paw*_*aga 5

有许多可能的解决方案来解决您的问题。我为您的媒体资源创建了一个自定义值解析器,它可以完美运行:

public class CustomResolver : IValueResolver<Source, Destination, Dictionary<string, object>>
{
    public Dictionary<string, object> Resolve(Source source, Destination destination, Dictionary<string, object> destMember, ResolutionContext context)
    {
        destMember = new Dictionary<string, object>();

        var flags = BindingFlags.Public | BindingFlags.Instance;
        var sourceProperties = typeof(Source).GetProperties(flags);

        foreach (var property in sourceProperties)
        {
            if (typeof(Destination).GetProperty(property.Name, flags) == null)
            {
                destMember.Add(property.Name, property.GetValue(source));
            }
        }

        return destMember;
    }
}
Run Code Online (Sandbox Code Playgroud)

如何使用它?

static void Main(string[] args)
{
    Mapper.Initialize(cfg => {
        cfg.CreateMap<Source, Destination>()
            .ForMember(dest => dest.D, opt => opt.ResolveUsing<CustomResolver>());
    });

    var source = new Source { A = 1, B = 2, C = 3 };

    var result = Mapper.Map<Source, Destination>(source);
}

public class Source
{
    public int A { get; set; }
    public int B { get; set; }
    public int C { get; set; }
}

public class Destination
{
    public int A { get; set; }
    public Dictionary<string, object> D { get; set; }
}
Run Code Online (Sandbox Code Playgroud)


小智 5

我喜欢 Pawel 的解决方案,因为它更通用。如果您想要更简单但不太通用的东西,您可以像这样初始化映射器:

    Mapper.Initialize(cfg => {
                          cfg.CreateMap<Source, Destination>()
                              .ForMember(dest => dest.D, 
                                         opt => opt.MapFrom(r => new Dictionary<string,object>(){{ "B", r.B},{ "C", r.C}}));
    });
Run Code Online (Sandbox Code Playgroud)