Automapper로 하나의 속성 매핑 무시


285

Automapper를 사용하고 있으며 다음 시나리오가 있습니다. OrderModel 클래스에는 데이터베이스에없는 'ProductName'이라는 속성이 있습니다. 그래서 매핑을 시도 할 때 :

Mapper.CreateMap<OrderModel, Orders>(); 

예외가 발생합니다.

"Project.ViewModels.OrderModel의 다음 1 개의 특성이 맵핑되지 않았습니다 : 'ProductName'

AutoMapper의 Wiki for Projections 에서 반대의 경우 읽었습니다 (추가 속성은 실제로 내 경우가 아닌 소스가 아닙니다)

오토 매퍼가이 속성을 매핑하지 않도록하려면 어떻게해야합니까?


7
Automapper는 그런 식으로 작동하지 않습니다. 대상 객체의 속성에만 관심이 있습니다. src는 100 개의 추가 속성을 포함 할 수 있습니다. Automapper는 dest 속성 만 매핑합니다. 매핑 예외를 발생시키는 다른 것이 있어야합니다. 작동하지 않는 코드를 게시 할 수 있습니까?
PatrickSteele

그것은 당신이 자동으로 요구하는 것을 수행합니다. 명확히하는 코드를 게시하십시오
BeRecursive


3
@Patrick AutoMapper는 분석법 / 속성 이름을 분석하는 몇 가지 트릭을 수행합니다. 대상과 정확히 일치하지 않더라도 의도하지 않게 매핑 된 속성이 소스에있을 수 있습니다. 이것이 발생하는 경우이를 방지하기 위해 ForSourceMember (... Ignore ())가있는 이유입니다.
AaronLS

답변:


478

지미 보가드 (Jimmy Bogard) CreateMap<Foo, Bar>().ForMember(x => x.Blarg, opt => opt.Ignore());

그것은에있어 자신의 블로그에 코멘트 중 하나 .


13
또한, CreateMap<Foo, Bar>().ForSourceMember(x => x.Blarg, opt => opt.Ignore());유용 할 수 있습니다
stackoverfloweth

5
@stackoverfloweth 그런 의미 CreateMap<SourceType, DestType> (MemberList.Source).ForSourceMember(x => x.MySourceProperty, opt => opt.DoNotValidate())인가요?
monty

12
ForSourceMember에서 무시는 DoNotValidate로 대체되었습니다 : github.com/AutoMapper/AutoMapper/blob/master/docs/…
Jamie

@Jamie @monty-이 re를 업데이트하기 시작했습니다 : 귀하의 의견이지만 구문 변경이 프로젝션 케이스에만 영향을 미치는 것처럼 보입니다 (소스 속성을 무시해야합니다). OP의 요청은 대상 속성을 무시하는 것이므로 Ignore()올바른 구문으로 유지됩니다. 인터페이스 Ignore에 대한 구문 변경 이 이루어 ISourceMemberConfigurationExpression졌지만 분리되지 않은 인터페이스에서는 변경되지 않았기 때문 IMemberConfigurationExpression`3입니다.
smartcaveman

2
@Franva ForMember ()는 실제로 "ForDestinationMember ()"입니다
rvnlord

243

나는 아마도 완벽 주의자 일 것이다. ForMember (..., x => x.Ignore ()) 구문이 마음에 들지 않습니다. 그것은 작은 일이지만 그것은 나에게 중요합니다. 좀 더 멋지게 만들기 위해이 확장 방법을 작성했습니다.

public static IMappingExpression<TSource, TDestination> Ignore<TSource, TDestination>(
    this IMappingExpression<TSource, TDestination> map,
    Expression<Func<TDestination, object>> selector)
{
    map.ForMember(selector, config => config.Ignore());
    return map;
}

다음과 같이 사용할 수 있습니다.

Mapper.CreateMap<JsonRecord, DatabaseRecord>()
        .Ignore(record => record.Field)
        .Ignore(record => record.AnotherField)
        .Ignore(record => record.Etc);

을 사용하여 다시 작성할 수도 params있지만 람다가 많은 메소드의 모양은 마음에 들지 않습니다.


6
나는 이것이 최초의 질문을 넘어선다는 것을 알고 있지만, 나는이 답변을 정말 좋아합니다. 깨끗하고, 읽고 이해하기 쉽고 즉시 이해하고 재사용하기 쉽습니다.
Lski

관련 params: 단일 람다 내부에서 선택기 배열을 반환 한 다음 각 선택기에 매핑 foreach하거나 Select()어쩌면 덜 지저분하지 않을 수도 있습니다.
jpaugh

감사합니다 @Steve Rukuts, 소스 멤버를 무시하기 위해 확장 방법을 찾고있는 사람은이 공용 정적 IMappingExpression <TSource, TDestination> IgnoreSourceValidation <TSource, TDestination> (this IMappingExpression <TSource, TDestination> 맵, Expression <Func <TSource , object >> selector) {map.ForSourceMember (선택기, 구성 => config.DoNotValidate ()); 반환지도; }
Jason Dias

79

당신은 이것을 할 수 있습니다 :

conf.CreateMap<SourceType, DestinationType>()
   .ForSourceMember(x => x.SourceProperty, y => y.Ignore());

automapper에는 ForSourceMember 확장자가 있습니까?
사용됨

나는 이것을 현재하고 있지만,이 모든 무시를하지 않아도되는 것이 이상적이다 ... : /
Tom Stickel

실제로지도를 만들 때가 아니라 실제로지도를 작성할 때 무시할 수있는 방법이 있는지 아십니까?
Sam 나는 오전


3
질문에 주어진 시나리오의 경우, 이것이 정답입니다. 현재 허용되는 답변은 대상 객체의 속성 매핑을 무시합니다. 이 질문은 소스 객체에서 매핑을 무시하는 것에 대한 질문입니다.
Rob S.

28

이 작업을 자동으로 수행하려는 모든 사람에게 해당 확장 방법을 사용하여 대상 유형의 기존 속성이 아닌 속성을 무시할 수 있습니다.

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

팁을위한 Can Gencer 덕분에 :)

출처 : http://cangencer.wordpress.com/2011/06/08/auto-ignore-non-existing-properties-with-automapper/



1
IMapper를 주입 할 때는 작동하지 않습니다. MapM.GetAllTypeMaps가 최신 버전의 AutoMapper에 없습니다. 또한 AutoMapper.Profile에서 맵을 설정 한 다음 IMapper를 주입하면 "매퍼가 초기화되지 않았습니다. 적절한 구성으로 초기화를 호출하십시오. 컨테이너를 통해 매퍼 인스턴스를 사용하려는 경우 또는 다른 방법으로 확인하십시오. 정적 Mapper.Map 메소드를 호출하지 않고 ProjectTo 또는 UseAsDataSource 확장 메소드를 사용하는 경우 적절한 IConfigurationProvider 인스턴스를 전달해야합니다. "
Ristogod

난 그냥 'Mapper' does not contain a definition for 'GetAllTypeMaps' [DSSTools]..
Bassie

2
@Bassie 사용 Mapper.Configuration.GetAllTypeMaps() 소스
마이크 Bovenlander

28

이제 (AutoMapper 2.0) IgnoreMap속성이 있는데, 약간 무거운 IMHO 인 유창한 구문 대신 사용할 것입니다.


35
ignore 속성은 응용 프로그램을 통해 자동 매퍼를 누설합니다.
Phill

11
AutoMapper는 모든 곳에서 누출되는 것을 신경 쓰지 않는 것입니다. ;)
Pawel Krakowiak

4
당신은 항상 파생을 고려할 수 있습니다 IgnoreMapAttribute.
Alapago

1
많은 객체에 상속 된 기본 속성을 무시하는 좋은 방법입니다. 모든 매핑 구성에서 무시할 필요가 없습니다.
체이스 플 로렐

23

뷰 모델을 다시 도메인 모델에 매핑 할 때 대상 멤버 목록이 아닌 소스 멤버 목록의 유효성을 검사하는 것이 훨씬 깔끔합니다.

Mapper.CreateMap<OrderModel, Orders>(MemberList.Source); 

이제 내 Ignore()도메인 클래스에 속성을 추가 할 때마다 매핑 유효성 검사가 실패하지 않아 다른 확인이 필요 합니다.


7
이것은 내가 찾은 것이므로 훨씬 간단한 DTO에서 도메인 객체 속성의 하위 집합 만 수정할 때 유용합니다.
Adam Tolley

5
이것은 답변 아이들입니다, 초보자가 혼동하지 않도록 공식적으로 만드십시오
Piotr M

0

무시해야하는 속성에서 IgnoreAttribute를 사용할 수 있습니다.


2
그것 [IgnoreMap]에서IgnoreMapAttribute
fiorebat

-5

안녕하세요 모두 사용하십시오.이 기능은 정상적으로 작동합니다 ... 자동 매퍼가 여러 번 사용하려면 C #의 ForMember

        if (promotionCode.Any())
        {
            Mapper.Reset();
            Mapper.CreateMap<PromotionCode, PromotionCodeEntity>().ForMember(d => d.serverTime, o => o.MapFrom(s => s.promotionCodeId == null ? "date" : String.Format("{0:dd/MM/yyyy h:mm:ss tt}", DateTime.UtcNow.AddHours(7.0))))
                .ForMember(d => d.day, p => p.MapFrom(s => s.code != "" ? LeftTime(Convert.ToInt32(s.quantity), Convert.ToString(s.expiryDate), Convert.ToString(DateTime.UtcNow.AddHours(7.0))) : "Day"))
                .ForMember(d => d.subCategoryname, o => o.MapFrom(s => s.subCategoryId == 0 ? "" : Convert.ToString(subCategory.Where(z => z.subCategoryId.Equals(s.subCategoryId)).FirstOrDefault().subCategoryName)))
                .ForMember(d => d.optionalCategoryName, o => o.MapFrom(s => s.optCategoryId == 0 ? "" : Convert.ToString(optionalCategory.Where(z => z.optCategoryId.Equals(s.optCategoryId)).FirstOrDefault().optCategoryName)))
                .ForMember(d => d.logoImg, o => o.MapFrom(s => s.vendorId == 0 ? "" : Convert.ToString(vendorImg.Where(z => z.vendorId.Equals(s.vendorId)).FirstOrDefault().logoImg)))
                .ForMember(d => d.expiryDate, o => o.MapFrom(s => s.expiryDate == null ? "" : String.Format("{0:dd/MM/yyyy h:mm:ss tt}", s.expiryDate))); 
            var userPromotionModel = Mapper.Map<List<PromotionCode>, List<PromotionCodeEntity>>(promotionCode);
            return userPromotionModel;
        }
        return null;
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.