2012-12-21 31 views
12

Tôi có thể sử dụng ánh xạ thừa kế trong AutoMapper (v2.2) cho các bản đồ có cùng loại Nguồn nhưng loại đích khác nhau không?AutoMapper - ánh xạ thừa kế không hoạt động, cùng nguồn, nhiều đích

Tôi có tình trạng này cơ bản (các lớp thực có nhiều tài sản hơn):

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

ViewModelAViewModelB là cơ quan đại diện khác nhau của lớp Entity cùng:

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

Tôi muốn tái sử dụng ánh xạ tương tự cho BaseViewModel cho từng Chế độ xem, chẳng hạn như:

Mapper.CreateMap<Entity, BaseViewModel>() 
    .Include<Entity, ViewModelA>() 
    .Include<Entity, ViewModelB>() 
    .ForMember(x => x.CommonProperty, y => y.MapFrom(z => z.Property1)); 

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

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

Nhưng thật không may, điều này dường như không hoạt động. Cuộc gọi như thế này:

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

kết quả trong model đã PropertyA ánh xạ, nhưng không CommonProperty. Tôi tin rằng tôi đang theo dõi các ví dụ trong https://github.com/AutoMapper/AutoMapper/wiki/Mapping-inheritance đúng cách, nhưng tôi e rằng có nhiều bản đồ được tạo với cùng một loại Nguồn đang cắt AutoMapper.

Mọi thông tin chi tiết? Tôi thích ý tưởng nhóm các ánh xạ lớp cơ sở với nhau, nhưng điều này dường như không hoạt động.

+1

Đối với người đọc tương lai của câu hỏi này - có vẻ như AutoMapper đã sửa lỗi này kể từ khi câu hỏi được hỏi. –

+0

Tôi đang cố gắng làm điều tương tự ở đây, nhưng tôi đang cố gắng làm: 'var model = Mapper.Map (thực thể)' nhưng nó trả về một thể hiện của ViewModelA, không phải là Ví dụ của BaseViewModel, thậm chí tôi nghĩ rằng tôi đang nói với hàm Map để trả về một kiểu BaseViewModel. Tôi đang sử dụng Automapper 3.0, có vẻ như lỗi gốc từ 2.2 đã được giải quyết. – njkremer

+0

Bài đăng SO này đã giúp tôi giải quyết vấn đề của tôi và có hiệu quả mong muốn để hoạt động. http://stackoverflow.com/questions/27317719/automapper-how-to-not-repeat-mapping-config-from-complex-type-to-base-class – njkremer

Trả lời

14

Thật không may trong trường hợp này, AutoMapper dường như chỉ đăng ký một ánh xạ lớp con cho mỗi loại nguồn, kiểu cuối cùng (ViewModelB). Điều này có thể được thiết kế để làm việc với các cấu trúc phân cấp song song, không phải với một kiểu nguồn duy nhất.

Để làm việc xung quanh này, bạn có thể đóng gói các ánh xạ phổ biến ở một phương pháp khuyến nông:

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

Và sử dụng nó trong các ánh xạ lớp cá nhân:

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 để sử dụng lại mã! – kdawg

+0

Cảm ơn nhưng không làm việc cho tôi. Bạn có thể vui lòng xem [Sử dụng AutoMapper để ánh xạ các lớp cơ sở] (http://stackoverflow.com/questions/39425775/using-automapper-to-map-base-classes) câu hỏi? –

+0

@ClintEastwood url của bạn không hoạt động – huoxudong125

0

Yo có thể làm như đây

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

Có mã mở rộng

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

} 
Các vấn đề liên quan