我想实现这里描述的东西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。
那么我该如何实现呢?我有更好的选择吗?
谢谢
最简单的方法是定义转换运算符:
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<>);
}
}