2013-03-11 12 views
11

Czy w ogóle Automapper ignoruje wszystkie właściwości określonego typu? Próbujemy poprawić jakość naszego kodu poprzez sprawdzenie odwzorowań Automapper, ale konieczność wprowadzenia .Ignore() dla wszystkich IEnumerable<SelectListItem>, które są zawsze ręcznie tworzone, powoduje tarcie i spowalnia rozwój.Automapper - zignoruj ​​wszystkie pozycje IEnumerable <SelectListItem>

Wszelkie pomysły?

Możliwa Idea po utworzeniu odwzorowania:

var existingMaps = Mapper.GetAllTypeMaps(); 
    foreach (var property in existingMaps) 
    { 
     foreach (var propertyInfo in property.DestinationType.GetProperties()) 
     { 
      if (propertyInfo.PropertyType == typeof(List<SelectListItem>) || propertyInfo.PropertyType == typeof(IEnumerable<SelectListItem>)) 
      { 
       property.FindOrCreatePropertyMapFor(new PropertyAccessor(propertyInfo)).Ignore(); 
      } 
     } 
    } 

Odpowiedz

17

Automapper obecnie nie obsługuje właściwość typu oparciu ignoruje.

Obecnie istnieją trzy sposoby, aby ignorować właściwości:

  • użyć opcji Ignore() podczas tworzenia odwzorowania

    Mapper.CreateMap<Source, Dest>() 
        .ForMember(d => d.IgnoreMe, opt => opt.Ignore()); 
    

    to czego chcesz uniknąć.

  • Adnotacje na swoim IEnumerable<SelectListItem> właściwości z The IgnoreMapAttribute

  • Jeśli IEnumerable<SelectListItem> nazwy właściwości wykonaj jakąś konwencję nazewnictwa. Na przykład. wszystko im zacząć ze słowem "Select" można użyć metody AddGlobalIgnore ignorować je globalnie:

    Mapper.Initialize(c => c.AddGlobalIgnore("Select")); 
    

    ale z tym można dopasować tylko z rozruchów.

Jednak można utworzyć metodę rozszerzenia wygodą dla pierwszych opcji, które będą automatycznie ignorować właściwości danego rodzaju podczas rozmowy CreateMap:

public static class MappingExpressionExtensions 
{ 
    public static IMappingExpression<TSource, TDest> 
     IgnorePropertiesOfType<TSource, TDest>(
     this IMappingExpression<TSource, TDest> mappingExpression, 
     Type typeToIgnore 
     ) 
    { 
     var destInfo = new TypeInfo(typeof(TDest)); 
     foreach (var destProperty in destInfo.GetPublicWriteAccessors() 
      .OfType<PropertyInfo>() 
      .Where(p => p.PropertyType == typeToIgnore)) 
     { 
      mappingExpression = mappingExpression 
       .ForMember(destProperty.Name, opt => opt.Ignore()); 
     } 

     return mappingExpression; 
    } 
} 

i można użyć go w następujący sposób :

Mapper.CreateMap<Source, Dest>() 
    .IgnorePropertiesOfType(typeof(IEnumerable<SelectListItem>)); 

Więc to jeszcze nie będzie globalne rozwiązanie, ale nie masz do listy właściwości, które powinny być ignorowane, a to działa na stwardnienie właściwa więzi tego samego typu.

Jeśli nie boi się dostać w swoje ręce brudne:

Obecnie istnieje bardzo hacky rozwiązanie, które idzie dość głęboko do wewnętrznych części Automapper.Nie wiem, jak to jest publiczne API więc ten hamulec rozwiązanie może w filmie:

Możesz zapisać się na ConfigurationStore „s TypeMapCreated imprezy

((ConfigurationStore)Mapper.Configuration).TypeMapCreated += OnTypeMapCreated; 

i dodać typ oparciu ignorować bezpośrednio na utworzony TypeMap przypadki:

private void OnTypeMapCreated(object sender, TypeMapCreatedEventArgs e) 
{ 
    foreach (var propertyInfo in e.TypeMap.DestinationType.GetProperties()) 
    { 
     if (propertyInfo.PropertyType == typeof (IEnumerable<SelectListItem>)) 
     { 
      e.TypeMap.FindOrCreatePropertyMapFor(
       new PropertyAccessor(propertyInfo)).Ignore(); 
     } 
    } 
} 
+0

Dzięki tak znalazłem AddGlobalIgnore, ale chciałem zrobić to na typ. IgnorePropertiesOfType wygląda dobrze dzięki. Po prostu denerwujące, musimy dodać to do setek maszyn wirtualnych. Więc nie ma możliwości przeszukiwania wszystkich zmapowanych modeli i poprzez odbicie znaleźć właściwości z typem IEnumerable , a następnie zastosować atrybut ignorowania? – GraemeMiller

+0

Aby dynamicznie dodawać atrybuty, będziesz coś, co wstrzykuje IL jak Postharp. Jednak znalazłem raczej brudny/hacky rozwiązanie golbal. Zaktualizuję moją odpowiedź. – nemesv

+0

Tak, tylko patrzyłem na źródło. Widziałem, gdzie GlobalIgnore został wciągnięty, myślał o zmianie źródła dla nas, ale wygląda na to, że to wystarczy! Dzięki – GraemeMiller

0

Jeśli natkniesz się na to teraz wydaje się, że istnieje inny sposób.

Mapper.Initialize(cfg => 
{ 
    cfg.ShouldMapProperty = pi => pi.PropertyType != typeof(ICommand); 
}); 

Nie zaglądałem, kiedy to zostało wprowadzone. Wygląda na to, że zablokuje lub zezwoli na filtrowanie tego. Zobacz: AutoMapper Configuration

Powiązane problemy