문제

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

업데이트: 명백히 사용자 지정 매핑이 포함되어 있으므로 올바르게 작동하지 않습니다. 먼저 ingyeallnonexisting을 호출 한 다음 나중에 사용자 정의 매핑을하는 경우에도 여전히 작동 할 수 있다고 생각합니다.

Schdr 은이 질문에 대한 해결책 (이 질문에 대한 답변)이 있습니다. Mapper.GetAllTypeMaps() 어떤 속성이 맵핑되지 않은지 알아 내고 자동으로 무시하십시오. 나에게 더 강력한 해결책 인 것 같습니다.

다른 팁

기존지도를 덮어 쓰지 않도록 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<destinationModel, sourceModel>(MemberList.Source);  

이제 Automapper는 모든 소스 필드가 매핑되었지만 다른 방식으로 맵핑되지 않았 음을 확인해야한다는 것을 알고 있습니다.

당신은 또한 사용할 수 있습니다 :

Mapper.CreateMap<destinationModel, sourceModel>(MemberList.Destination);  

나는 이것을 다음과 같이 할 수 있었다.

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

사용하는 사람들을 위해 비 정적 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;
}

여기서 중요한 것은 정적 API가 제거되면 코드는 다음과 같은 코드입니다. Mapper.FindTypeMapFor 더 이상 작동하지 않으므로 expression.TypeMap 필드.

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

이 경우 출력 객체에 대한 ID 필드 만 해결됩니다. 다른 모든 것이 건너 뜁니다. 매력처럼 작동합니다. 더 이상 까다로운 확장이 필요하지 않은 것 같습니다!

Automapper 4.2에 대한 Robert Schroeder의 답변을 업데이트했습니다. 비 정적 맵퍼 구성을 사용하면 사용할 수 없습니다 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;
}

특정 회원이 무시되도록 어떻게 지정하고 싶습니까? 컨벤션, 기본 클래스 또는 신청하고 싶은 속성이 있습니까? 모든 매핑을 명시 적으로 지정하는 비즈니스에 들어가면 Automapper에서 어떤 가치를 얻을 수 있는지 잘 모르겠습니다.

이것은 오래된 질문처럼 보이지만 다른 사람이 내가있는 사람에 대해 내 대답을 게시 할 것이라고 생각했습니다.

나는 Allmembers와 결합 된 구성, 객체 이니셜 라이저를 사용합니다.

    Mapper.CreateMap<Source, Target>()
        .ConstructUsing(
            f =>
                new Target
                    {
                        PropVal1 = f.PropVal1,
                        PropObj2 = Map<PropObj2Class>(f.PropObj2),
                        PropVal4 = f.PropVal4
                    })
        .ForAllMembers(a => a.Ignore());

많은 회원을 무시하는 것에 대한 유일한 인프라는이 스레드입니다. http://groups.google.com/group/automapper-users/browse_thread/thread/9928ce9f2ffa641f . CommonBaseClassConfiguration을 제공하는 데 사용 된 트릭을 사용하여 유사한 클래스의 공통 속성을 무시할 수 있다고 생각합니다.
그리고 "나머지 무시"기능에 대한 정보는 없습니다. 나는 이전에 코드를 보았고 그러한 기능을 추가하기가 매우 어려울 것 같습니다. 또한 일부 속성을 사용하고 속성을 무시하고 마크를 표시하고 모든 표시된 속성을 무시하기 위해 일반/공통 코드를 추가 할 수 있습니다.

나는 이것이 오래된 질문이라는 것을 알고 있지만 @jmoerdyk 당신의 질문에 :

프로파일의 Chained Createmap () 표현식에서 이것을 어떻게 사용 하시겠습니까?

당신은 이것을 사용할 수 있습니다 대답 이와 같이 프로파일 CTOR 내부

this.IgnoreUnmapped();
CreateMap<TSource, Tdestination>(MemberList.Destination)
.ForMember(dest => dest.SomeProp, opt => opt.MapFrom(src => src.OtherProp));

이와 같이 필요로 만 덮어 쓰는 것보다 Allmembers에 사용할 수 있습니다.

public static IMappingExpression<TSource, TDest> IgnoreAll<TSource, TDest>(this IMappingExpression<TSource, TDest> expression)
        {
            expression.ForAllMembers(opt => opt.Ignore());
            return expression;
        }

조심하십시오. 모든 것을 무시하고 사용자 정의 매핑을 추가하지 않으면 이미 무시되고 작동하지 않습니다.

또한 Automapper에 대한 단위 테스트가 있다면 말하고 싶습니다. 그리고 모든 속성이 올바르게 매핑 된 모든 모델을 테스트합니다. 그러한 확장 방법을 사용해서는 안됩니다.

당신은 명시 적으로 무시하는 것을 써야합니다

3.3.1의 버전에서는 간단히 사용할 수 있습니다 IgnoreAllPropertiesWithAnInaccessibleSetter() 또는 IgnoreAllSourcePropertiesWithAnInaccessibleSetter() 행동 양식.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top