.net AutoMapper -如何添加自定义IObjectMapper

bvjxkvbb  于 2023-05-19  发布在  .NET
关注(0)|答案(1)|浏览(190)

我想实现像这里描述的https://stackoverflow.com/a/34956681/6051621https://dotnetfiddle.net/vWmRiY
这个想法是打开一个Wrapper<T>。由于Wrapper<T>T的Map似乎不支持开箱即用,因此可能的解决方案之一是注册一个自定义IObjectMapper。问题是MapperRegistry现在是内部的https://github.com/AutoMapper/AutoMapper/blob/master/src/AutoMapper/Mappers/MapperRegistry.cs#LL3C29-L3C31。那么我如何才能实现这一点呢?我有更好的选择吗?
谢谢你

hjzp0vay

hjzp0vay1#

最简单的方法是定义conversion operators

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);

和示例Map器,让您开始:

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<>);
    }
}

相关问题