AutoMapper - 如何添加自定义 IObjectMapper

问题描述 投票:0回答:1

我想实现这里描述的东西https://stackoverflow.com/a/34956681/6051621https://dotnetfiddle.net/vWmRiY.

想法是打开一个

Wrapper<T>
。由于开箱即用似乎不支持将
Wrapper<T>
映射到
T
,因此可能的解决方案之一是注册自定义 IObjectMapper。 问题是 MapperRegistry 现在是内部的https://github.com/AutoMapper/AutoMapper/blob/master/src/AutoMapper/Mappers/MapperRegistry.cs#LL3C29-L3C31。 那么我该如何实现呢?我有更好的选择吗?

谢谢

c# .net automapper
1个回答
1
投票

最简单的方法是定义转换运算符

public class MyGenericWrapper<T>
{
    public T Value {get; set;}
    
    public static explicit operator MyGenericWrapper<T>(T p) => new MyGenericWrapper<T>
    {
        Value = p
    };
    
    public static explicit operator T(MyGenericWrapper<T> p) => p.Value;
}

但如果你不想,那么你可以尝试以下操作:

var config = new MapperConfiguration(cfg =>
{
    cfg.Internal().Mappers.Add(new SourceWrapperMapper());
    cfg.Internal().Mappers.Add(new DestinationWrapperMapper());
    cfg.CreateMap<Dto, Entity>();
    cfg.CreateMap<Entity, Dto>();
});

var mapper = config.CreateMapper();
var entity = mapper.Map<Entity>(new Dto
{
    SomeValue = new MyGenericWrapper<int>{Value = 42}
});
        
var dto = mapper.Map<Dto>(entity);

让您入门的示例映射器:

public class SourceWrapperMapper : IObjectMapper
{ 
    public bool IsMatch(TypePair context) => IsWrappedValue(context.SourceType);

    public Expression MapExpression(IGlobalConfiguration configuration,
        ProfileMap profileMap,
        MemberMap memberMap,
        Expression sourceExpression,
        Expression destExpression) =>
        Expression.PropertyOrField(sourceExpression, nameof(MyGenericWrapper<int>.Value));

    private static bool IsWrappedValue(Type type)
    {
        return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(MyGenericWrapper<>);
    }
}
public class DestinationWrapperMapper : IObjectMapper
{ 
    public bool IsMatch(TypePair context) => IsWrappedValue(context.DestinationType);

    public Expression MapExpression(IGlobalConfiguration configuration,
        ProfileMap profileMap,
        MemberMap memberMap,
        Expression sourceExpression,
        Expression destExpression)
    {
        var wrappedType = memberMap.DestinationType.GenericTypeArguments.First();
        return Expression.Call(Mi.MakeGenericMethod(wrappedType), configuration.MapExpression(profileMap,
            new TypePair(memberMap.SourceType, wrappedType),
            sourceExpression,
            memberMap));
    }

    public static MyGenericWrapper<T> Wrap<T>(T p) => new MyGenericWrapper<T>
    {
        Value = p
    };

    private static MethodInfo Mi =
        typeof(DestinationWrapperMapper).GetMethod(nameof(Wrap), BindingFlags.Public | BindingFlags.Static);
    private static bool IsWrappedValue(Type type)
    {
        return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(MyGenericWrapper<>);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.