简体   繁体   English

如何使用AutoMapper和ConstructUsing创建通用映射

[英]How to create generic mapping with AutoMapper and ConstructUsing

I have a map configuration: 我有一个地图配置:

Mapper.Initialize(cfg =>
{
    cfg.CreateMap<IDictionary<int, MyType1>, List<MyType1>>().ConstructUsing(
        x0 => x0?.OrderBy(x => x.Key).Select(x => x.Value).ToList());
});

How can I change this to work with "all MyTypes"? 如何更改它以与“所有MyTypes”一起使用?

I want to convert from IDictionary<int, T> to List<T> for any T type. 我想将任何T类型从IDictionary<int, T>转换为List<T>

I found a very ugly solution: 我发现一个非常丑陋的解决方案:

cfg.CreateMap(typeof(IDictionary<,>), typeof(List<>)).ConstructUsing(
    x0 =>
    {
        if (x0 == null)
        {
            return null;
        }

        var dict = (IEnumerable)x0;
        var type = x0.GetType().GetGenericArguments()[1];
        var list = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(type));
        CastDictionaryEntry(dict).OrderBy(x => x.Key).ForEach(x => list.Add(x.Value));
        return list;
    }
);

and: 和:

static IEnumerable<DictionaryEntry> CastDictionaryEntry(IEnumerable dict)
{
    foreach (var item in dict)
    {
        yield return (DictionaryEntry)item;
    }
}

Is there any easier way to do this? 有没有更简单的方法可以做到这一点?

I think works, but then again I haven't tested against a broad set of inputs- 我认为可以,但是我仍然没有针对广泛的输入进行测试-

class ABC
    {
        public int MyProperty { get; set; }
        public int MyProperty2 { get; set; }
    }
    static List<T> ConfigureMap<T>(Dictionary<int, T> input) where T : class
    {
        AutoMapper.Mapper.Initialize(cfg => cfg.CreateMap(input.GetType(), typeof(List<T>))
        .ConstructUsing(Construct));

        return Mapper.Map<List<T>>(input);

    }

    private static object Construct(object arg1, ResolutionContext arg2)
    {
        if (arg1 != null)
        {
            var val = arg1 as IDictionary;
            var argument = val.GetType().GetGenericArguments()[1];
            if (val != null)
            {
                var type = Activator.CreateInstance(typeof(List<>).MakeGenericType(argument));

                foreach (var key in val.Keys)
                {
                    ((IList)type).Add(val[key]);
                }

                return type;
            }
        }

        return null;
    }

var so = new Dictionary<int, ABC> { { 1, new ABC { MyProperty = 10, MyProperty2 = 30 } } };
var dest = new List<ABC>();
var res = ConfigureMap<ABC>(so);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM