Igo*_*ejc 196 .net automapper
有没有办法告诉AutoMapper忽略除明确映射的属性之外的所有属性?
我有外部DTO类可能会从外部更改,我想避免指定要显式忽略的每个属性,因为添加新属性会在尝试将它们映射到我自己的对象时破坏功能(导致异常).
Rob*_*der 222
我已经更新了Can Gencer的扩展,不会覆盖任何现有的地图.
public static IMappingExpression<TSource, TDestination>
IgnoreAllNonExisting<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression)
{
var sourceType = typeof (TSource);
var destinationType = typeof (TDestination);
var existingMaps = Mapper.GetAllTypeMaps().First(x => x.SourceType.Equals(sourceType) && x.DestinationType.Equals(destinationType));
foreach (var property in existingMaps.GetUnmappedPropertyNames())
{
expression.ForMember(property, opt => opt.Ignore());
}
return expression;
}
Run Code Online (Sandbox Code Playgroud)
用法:
Mapper.CreateMap<SourceType, DestinationType>()
.ForMember(prop => x.Property, opt => opt.MapFrom(src => src.OtherProperty))
.IgnoreAllNonExisting();
Run Code Online (Sandbox Code Playgroud)
小智 218
根据我的理解,问题是目标上的字段在源中没有映射字段,这就是为什么要查找忽略那些非映射目标字段的方法.
您可以简单地使用,而不是实现和使用这些扩展方法
Mapper.CreateMap<destinationModel, sourceModel>(MemberList.Source);
Run Code Online (Sandbox Code Playgroud)
现在,automapper知道它只需要验证所有源字段是否已映射,而不是相反.
您还可以使用:
Mapper.CreateMap<destinationModel, sourceModel>(MemberList.Destination);
Run Code Online (Sandbox Code Playgroud)
小智 83
我已经能够通过以下方式实现这一目标:
Mapper.CreateMap<SourceType, DestinationType>().ForAllMembers(opt => opt.Ignore());
Mapper.CreateMap<SourceType, DestinationType>().ForMember(/*Do explicit mapping 1 here*/);
Mapper.CreateMap<SourceType, DestinationType>().ForMember(/*Do explicit mapping 2 here*/);
...
Run Code Online (Sandbox Code Playgroud)
注意:我使用的是AutoMapper v.2.0.
Can*_*cer 82
这是我编写的一种扩展方法,它忽略了目标上的所有非现有属性.不确定它是否仍然有用,因为问题超过两年,但我遇到了同样的问题,不得不添加大量的手动忽略调用.
public static IMappingExpression<TSource, TDestination> IgnoreAllNonExisting<TSource, TDestination>
(this IMappingExpression<TSource, TDestination> expression)
{
var flags = BindingFlags.Public | BindingFlags.Instance;
var sourceType = typeof (TSource);
var destinationProperties = typeof (TDestination).GetProperties(flags);
foreach (var property in destinationProperties)
{
if (sourceType.GetProperty(property.Name, flags) == null)
{
expression.ForMember(property.Name, opt => opt.Ignore());
}
}
return expression;
}
Run Code Online (Sandbox Code Playgroud)
用法:
Mapper.CreateMap<SourceType, DestinationType>()
.IgnoreAllNonExisting();
Run Code Online (Sandbox Code Playgroud)
更新:如果您有自定义映射,显然这不能正常工作,因为它会覆盖它们.我想如果先调用IgnoreAllNonExisting然后再调用自定义映射,它仍然可以工作.
schdr有一个解决方案(作为这个问题的答案),用于Mapper.GetAllTypeMaps()找出哪些属性未映射并自动忽略它们.对我来说似乎是一个更强大的解决方案.
ajb*_*ven 63
AutoMapper的5.0.0-beta-1版本引入了ForAllOtherMembers扩展方法,因此您现在可以执行此操作:
CreateMap<Source, Destination>()
.ForMember(d => d.Text, o => o.MapFrom(s => s.Name))
.ForMember(d => d.Value, o => o.MapFrom(s => s.Id))
.ForAllOtherMembers(opts => opts.Ignore());
Run Code Online (Sandbox Code Playgroud)
请注意,显式映射每个属性都有一个优势,因为当您忘记映射属性时,您将永远不会出现静默映射失败的问题.
也许在你的情况下,忽略所有其他成员并添加一个TODO回来并在这个类的更改频率稳定下来之后使这些成员显然是明智的.
Ric*_*ard 43
从AutoMapper 5.0开始,.TypeMap属性IMappingExpression已经消失,这意味着4.2解决方案不再有效.我创建了一个使用原始功能但使用不同语法的解决方案:
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<Src, Dest>();
cfg.IgnoreUnmapped(); // Ignores unmapped properties on all maps
cfg.IgnoreUnmapped<Src, Dest>(); // Ignores unmapped properties on specific map
});
// or add inside a profile
public class MyProfile : Profile
{
this.IgnoreUnmapped();
CreateMap<MyType1, MyType2>();
}
Run Code Online (Sandbox Code Playgroud)
执行:
public static class MapperExtensions
{
private static void IgnoreUnmappedProperties(TypeMap map, IMappingExpression expr)
{
foreach (string propName in map.GetUnmappedPropertyNames())
{
if (map.SourceType.GetProperty(propName) != null)
{
expr.ForSourceMember(propName, opt => opt.Ignore());
}
if (map.DestinationType.GetProperty(propName) != null)
{
expr.ForMember(propName, opt => opt.Ignore());
}
}
}
public static void IgnoreUnmapped(this IProfileExpression profile)
{
profile.ForAllMaps(IgnoreUnmappedProperties);
}
public static void IgnoreUnmapped(this IProfileExpression profile, Func<TypeMap, bool> filter)
{
profile.ForAllMaps((map, expr) =>
{
if (filter(map))
{
IgnoreUnmappedProperties(map, expr);
}
});
}
public static void IgnoreUnmapped(this IProfileExpression profile, Type src, Type dest)
{
profile.IgnoreUnmapped((TypeMap map) => map.SourceType == src && map.DestinationType == dest);
}
public static void IgnoreUnmapped<TSrc, TDest>(this IProfileExpression profile)
{
profile.IgnoreUnmapped(typeof(TSrc), typeof(TDest));
}
}
Run Code Online (Sandbox Code Playgroud)
Ira*_*chi 17
问题问题已经有几年了,但是使用当前版本的AutoMapper(3.2.1),这种扩展方法对我来说似乎更干净:
public static IMappingExpression<TSource, TDestination> IgnoreUnmappedProperties<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression)
{
var typeMap = Mapper.FindTypeMapFor<TSource, TDestination>();
if (typeMap != null)
{
foreach (var unmappedPropertyName in typeMap.GetUnmappedPropertyNames())
{
expression.ForMember(unmappedPropertyName, opt => opt.Ignore());
}
}
return expression;
}
Run Code Online (Sandbox Code Playgroud)
nic*_*k_w 16
对于那些谁正在使用的非静态API在4.2.0及以上版本,下面的扩展方法(发现这里的AutoMapperExtensions类)可用于:
// from http://stackoverflow.com/questions/954480/automapper-ignore-the-rest/6474397#6474397
public static IMappingExpression IgnoreAllNonExisting(this IMappingExpression expression)
{
foreach(var property in expression.TypeMap.GetUnmappedPropertyNames())
{
expression.ForMember(property, opt => opt.Ignore());
}
return expression;
}
Run Code Online (Sandbox Code Playgroud)
这里重要的是,一旦删除静态API,代码Mapper.FindTypeMapFor将不再起作用,因此使用该expression.TypeMap字段.
小智 16
对于Automapper 5.0,您可以跳过所有未映射的属性
.ForAllOtherMembers(X => x.Ignore());
在你的个人资料的最后.
例如:
internal class AccountInfoEntityToAccountDtoProfile : Profile
{
public AccountInfoEntityToAccountDtoProfile()
{
CreateMap<AccountInfoEntity, AccountDto>()
.ForMember(d => d.Id, e => e.MapFrom(s => s.BankAcctInfo.BankAcctFrom.AcctId))
.ForAllOtherMembers(x=>x.Ignore());
}
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,将仅解析输出对象的Id字段,将跳过所有其他字段.像魅力一样工作,似乎我们不再需要任何棘手的扩展!
mrm*_*hal 10
我更新了Robert Schroeder对AutoMapper 4.2的回答.使用非静态映射器配置,我们不能使用Mapper.GetAllTypeMaps(),但是expression具有对所需的引用TypeMap:
public static IMappingExpression<TSource, TDestination>
IgnoreAllNonExisting<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression)
{
foreach (var property in expression.TypeMap.GetUnmappedPropertyNames())
{
expression.ForMember(property, opt => opt.Ignore());
}
return expression;
}
Run Code Online (Sandbox Code Playgroud)
您希望如何指定忽略某些成员?是否有您想要应用的约定,基类或属性?一旦你开始明确指定所有映射的业务,我不确定你从AutoMapper中得到什么价值.
小智 7
这似乎是一个古老的问题,但我想我会回答其他任何看起来像我的人.
我使用ConstructUsing,对象初始化器与ForAllMembers一起忽略例如
Mapper.CreateMap<Source, Target>()
.ConstructUsing(
f =>
new Target
{
PropVal1 = f.PropVal1,
PropObj2 = Map<PropObj2Class>(f.PropObj2),
PropVal4 = f.PropVal4
})
.ForAllMembers(a => a.Ignore());
Run Code Online (Sandbox Code Playgroud)
小智 5
默认情况下,AutoMapper 使用目标类型来验证成员,但您可以使用MemberList.None选项跳过验证。
var configuration = new MapperConfiguration(cfg =>
cfg.CreateMap<Source2, Destination2>(MemberList.None);
);
Run Code Online (Sandbox Code Playgroud)
你可以在这里找到参考
| 归档时间: |
|
| 查看次数: |
67498 次 |
| 最近记录: |