2012-12-21 16 views
12

Aynı Kaynak türüne, ancak farklı Hedef türlerine sahip haritalar için AutoMapper (v2.2) öğesinde miras eşleştirmesi kullanabilir miyim? Ben yeniden kullanmak istediğinizAutoMapper - kalıtım eşlemesi çalışmıyor, aynı kaynak, çoklu hedefler

public class Entity 
{ 
    public int Property1 { get; set; } 
    public int Property2 { get; set; } 
    public int Property3 { get; set; } 
} 

:

public abstract class BaseViewModel 
{ 
    public int CommonProperty { get; set;} 
} 

public class ViewModelA : BaseViewModel 
{ 
    public int PropertyA { get; set; } 
} 

public class ViewModelB : BaseViewModel 
{ 
    public int PropertyB { get; set; } 
} 

ViewModelA ve ViewModelB aynı Varlık sınıfın farklı gösterimleri şunlardır:

Ben bu temel durum (gerçek sınıfları daha birçok özellikleri vardır) sahip Her bir ViewModel için BaseViewModel için aynı eşleştirmeler, örneğin:

Fakat maalesef bu işe yaramıyor. Bu gibi Aramalar:

var model = Mapper.Map<Entity, ViewModelA>(entity); 

sonuç model yılında PropertyA eşlenen değil CommonProperty sahip. https://github.com/AutoMapper/AutoMapper/wiki/Mapping-inheritance'daki örnekleri düzgün takip ettiğime inanıyorum, ama aynı Kaynak türü ile oluşturulmuş birden fazla haritanın AutoMapper'ı açmasından korkuyorum.

Herhangi bir anlayış? Base class mappings'i bir araya getirme fikrini çok seviyorum ama bu işe yaramıyor.

+1

Bu sorunun gelecekteki okuyucuları için - sorulan sorudan bu yana AutoMapper'ın bu sorunu çözdüğü anlaşılıyor. –

+0

Burada aynı şeyi yapmaya çalışıyorum, ancak yapmaya çalışıyorum: 'var model = Mapper.Map (varlık)' ancak ViewModelA örneğini döndürmek değil, bir BaseViewModel örneği, bir BaseViewModel türü döndürmek için Harita işlevini anlattığımı düşündüm. Automapper 3.0 kullanıyorum, bu yüzden 2.2'deki orijinal hata çözülmüş gibi görünüyor. – njkremer

+0

Bu SO gönderi, sorunumda bana yardımcı oldu ve çalışmak için istenen etkiyi elde etti. Kod yeniden kullanımı için http://stackoverflow.com/questions/27317719/automapper-how-to-not-repeat-mapping-config-from-complex-type-to-base-class – njkremer

cevap

14

Maalesef, bu durumda AutoMapper, her bir kaynak türü için yalnızca bir alt sınıf eşlemesi kaydettiriyor gibi görünüyor, sonuncusu (ViewModelB). Bu muhtemelen tek bir kaynak türü ile değil paralel hiyerarşilerle çalışmak üzere tasarlandı.

public static IMappingExpression<Entity, TDestination> MapBaseViewModel<TDestination>(this IMappingExpression<Entity, TDestination> map) 
    where TDestination : BaseViewModel { 
    return map.ForMember(x => x.CommonProperty, y => y.MapFrom(z => z.Property1)); 
} 

Ve bireysel alt sınıf eşleştirmeleri kullanmak:

bir uzantı yönteminde yaygın eşleştirmeleri sarabiliriz, Bu sorunu gidermek için

Mapper.CreateMap<Entity, ViewModelA>() 
    .MapBaseViewModel<ViewModelA>() 
    .ForMember(x => x.PropertyA, y => y.MapFrom(z => z.Property2)); 

Mapper.CreateMap<Entity, ViewModelB>() 
    .MapBaseViewModel<ViewModelB>() 
    .ForMember(x => x.PropertyB, y => y.MapFrom(z => z.Property3)); 
+4

+1! – kdawg

+0

Teşekkürler ama benim için işe yaramadı. [Temel Sınıfları eşleştirmek için AutoMapper kullanma] (http://stackoverflow.com/questions/39425775/using-automapper-to-map-base-classes) sorusuna bir göz atabilir misiniz? –

+0

@ClintEastwood URL'niz çalışmıyor – huoxudong125

0

Yo burada

gibi yapabilirsiniz
  CreateMap<Entity, ViewModelA>() 
      .InheritMapping(x => 
      { 
       x.IncludeDestinationBase<BaseViewModel>(); 
      }); 

Uzantı kodu var

public static class MapExtensions 
{   

    public static void InheritMapping<TSource, TDestination>(
     this IMappingExpression<TSource, TDestination> mappingExpression, 
     Action<InheritMappingExpresssion<TSource, TDestination>> action) 
    { 
     InheritMappingExpresssion<TSource, TDestination> x = 
      new InheritMappingExpresssion<TSource, TDestination>(mappingExpression); 
     action(x); 
     x.ConditionsForAll(); 
    } 

    private static bool NotAlreadyMapped(Type sourceType, Type desitnationType, ResolutionContext r, Type typeSourceCurrent, Type typeDestCurrent) 
    { 
     var result = !r.IsSourceValueNull && 
       Mapper.FindTypeMapFor(sourceType, desitnationType).GetPropertyMaps().Where(
        m => m.DestinationProperty.Name.Equals(r.MemberName)).Select(y => !y.IsMapped() 
        ).All(b => b); 
     return result; 
    } 
    public class InheritMappingExpresssion<TSource, TDestination> 
    { 
     private readonly IMappingExpression<TSource, TDestination> _sourcExpression; 
     public InheritMappingExpresssion(IMappingExpression<TSource, TDestination> sourcExpression) 
     { 
      _sourcExpression = sourcExpression; 
     } 
     public void IncludeSourceBase<TSourceBase>(
      bool ovverideExist = false) 
     { 
      Type sourceType = typeof (TSourceBase); 
      Type destinationType = typeof (TDestination); 
      if (!sourceType.IsAssignableFrom(typeof (TSource))) throw new NotSupportedException(); 
      Result(sourceType, destinationType); 
     } 
     public void IncludeDestinationBase<TDestinationBase>() 
     { 
      Type sourceType = typeof (TSource); 
      Type destinationType = typeof (TDestinationBase); 
      if (!destinationType.IsAssignableFrom(typeof (TDestination))) throw new NotSupportedException(); 
      Result(sourceType, destinationType); 
     } 
     public void IncludeBothBases<TSourceBase, TDestinatioBase>() 
     { 
      Type sourceType = typeof (TSourceBase); 
      Type destinationType = typeof (TDestinatioBase); 
      if (!sourceType.IsAssignableFrom(typeof (TSource))) throw new NotSupportedException(); 
      if (!destinationType.IsAssignableFrom(typeof (TDestination))) throw new NotSupportedException(); 
      Result(sourceType, destinationType); 
     } 
     internal void ConditionsForAll() 
     { 
      _sourcExpression.ForAllMembers(x => x.Condition(r => _conditions.All(c => c(r))));//указываем что все кондишены истинны 
     } 
     private List<Func<ResolutionContext, bool>> _conditions = new List<Func<ResolutionContext, bool>>(); 
     private void Result(Type typeSource, Type typeDest) 
     { 
       _sourcExpression.BeforeMap((x, y) => 
       { 
        Mapper.Map(x, y, typeSource, typeDest); 
       }); 
       _conditions.Add((r) => NotAlreadyMapped(typeSource, typeDest, r, typeof (TSource), typeof (TDestination))); 
     } 
    } 

}