[.net] AutoMapper : “나머지 무시”?
명시 적으로 매핑 된 속성을 제외한 모든 속성을 무시하도록 AutoMapper에 지시하는 방법이 있습니까?
외부에서 변경 될 수있는 외부 DTO 클래스가 있으며 새 속성을 추가하면 내 객체에 매핑하려고 할 때 기능 (예외 원인)이 손상되므로 명시 적으로 무시할 각 속성을 지정하지 마십시오.
답변
이것은 내가 작성한 확장 방법으로 대상의 기존 속성이 아닌 모든 속성을 무시합니다. 질문이 2 세 이상이므로 여전히 유용한 지 확실하지 않지만 많은 수동 무시 호출을 추가 해야하는 동일한 문제가 발생했습니다.
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;
}
용법:
Mapper.CreateMap<SourceType, DestinationType>()
.IgnoreAllNonExisting();
업데이트 : 분명히 사용자 정의 매핑이 덮어 쓰기 때문에 올바르게 작동하지 않습니다. IgnoreAllNonExisting을 먼저 호출 한 다음 나중에 사용자 지정 매핑을 호출하면 여전히 작동 할 수 있다고 생각합니다.
schdr에는 (이 질문에 대한 답변으로) Mapper.GetAllTypeMaps()
매핑되지 않은 속성을 찾고 자동으로 무시 하는 솔루션이 있습니다. 더 강력한 솔루션 인 것 같습니다.
답변
내가 이해 한 바에 따르면 소스에 매핑 된 필드가없는 대상에 필드가 있으므로 매핑되지 않은 대상 필드를 무시하는 방법을 찾고 있습니다.
이러한 확장 방법을 구현하고 사용하는 대신 간단하게 사용할 수 있습니다.
Mapper.CreateMap<sourceModel, destinationModel>(MemberList.Source);
이제 automapper는 모든 소스 필드가 맵핑되었지만 다른 방식으로 맵핑되지 않았 음을 검증해야한다는 것을 알고 있습니다.
다음을 사용할 수도 있습니다.
Mapper.CreateMap<sourceModel, destinationModel>(MemberList.Destination);
답변
기존지도를 덮어 쓰지 않도록 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;
}
용법:
Mapper.CreateMap<SourceType, DestinationType>()
.ForMember(prop => x.Property, opt => opt.MapFrom(src => src.OtherProperty))
.IgnoreAllNonExisting();
답변
나는 다음과 같은 방법으로 이것을 할 수 있었다.
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*/);
...
참고 : AutoMapper v.2.0을 사용하고 있습니다.
답변
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());
속성 매핑을 잊었을 때 발생하는 자동 실패 매핑 문제는 발생하지 않으므로 각 속성을 명시 적으로 매핑하는 이점이 있습니다.
아마도 귀하의 경우에는 다른 모든 멤버를 무시 TODO
하고이 클래스에 대한 변경 빈도가 정해진 후 되돌아 와서이를 명시 하는 것이 현명 할 수 있습니다 .
답변
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>();
}
이행:
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));
}
}
답변
질문을한지 몇 년이 지났지 만 현재 확장 버전의 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;
}