2013-03-11 41 views
11

Automapper是否有忽略某種類型的所有屬性?我們試圖通過驗證Automapper映射來提高代碼的質量,但必須爲所有IEnumerable<SelectListItem>放置一個.Ignore(),而這些總是手動創建的,正在創建摩擦並減慢開發速度。Automapper - 忽略IEnumerable的所有項目<SelectListItem>

任何想法?

創建映射後可能的想法:

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

回答

17

Automapper目前不支持基於類型屬性忽略。

目前有三種方式可以忽略的屬性:

  • 創建映射

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

    時,這是要避免的使用Ignore()選項。在你的IEnumerable<SelectListItem>性能與

  • 註釋的IgnoreMapAttribute

  • 如果您IEnumerable<SelectListItem>屬性名遵循一定的命名約定。例如。所有的人開始用這個詞"Select"可以使用AddGlobalIgnore方法在全球忽略它們:

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

    但這個你只能與開始相匹配。

但是,您可以創建,當你調用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; 
    } 
} 

而且你可以用下面的方式來使用它:

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

所以它仍然不會成爲一個全球性的解決方案,但你沒有列出哪些屬性需要被忽略,它適用於多種適當的關係相同的類型。

如果你不害怕讓你的手髒:

目前肚裏相當深入Automapper的內部非常哈克解決方案。我不知道公衆是怎麼這個API,因此在功能這個解決方案可能剎車:

您可以訂閱的ConfigurationStoreTypeMapCreated事件

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

,並添加基於類型直接在創建忽視TypeMap實例:

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

謝謝是的,我已經找到了AddGlobalIgnore,但想要做的類型。 IgnorePropertiesOfType看起來不錯,謝謝。只是很煩人,我們不得不將它添加到數百個虛擬機中。因此,無法搜索所有映射模型並通過反射查找具有IEnumerable 類型的屬性,然後應用ignore屬性? – GraemeMiller 2013-03-11 13:57:29

+0

要動態添加屬性,您需要注入像Postharp一樣的IL。不過,我發現了一個相當髒/哈克的全球解決方案。我會更新我的答案。 – nemesv 2013-03-11 14:17:03

+0

是的,只是看着源頭。我看到GlobalIgnore被牽扯到哪裏想改變我們的源代碼,但是這看起來好像有用!謝謝 – GraemeMiller 2013-03-11 14:24:05

0

如果您現在遇到此問題,那麼看起來還有其他方法。

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

我沒有看到什麼時候這是介紹。這似乎會阻止或允許您過濾此。 看到這個:AutoMapper Configuration