2017-03-06 52 views
1

我有一個Person類,其中包含通過訪問Item屬性延遲加載(自定義延遲加載)個人地址數據的屬性。我希望它被映射到一個POCO類。它怎麼能做到?具有自定義延遲加載對象的自動映射器

另外,是否有可能僅當它有數據時纔會映射(檢查HasData屬性),如果沒有數據,則映射爲null? 這些都是源類:

public class SourcePerson 
{ 
    public string Name { get; set; } 

    public MyLazyLoadingObject<SourceAddress> Address; 
} 

public class SourceAddress 
{ 
    public string City { get; set; } 

    public string Country { get; set; } 
} 

這是自定義的延遲加載類(簡體):

public class MyLazyLoadingObject<T> 
{ 
    private int? _id; 
    private T _object; 

    public T Item 
    { 
     get 
     { 
      if (!_object.IsReaded) 
      { 
       _object.Read(); 
      } 

      return _object; 
     } 
    } 

    public bool HasData 
    { 
     get 
     { 
      return _id.HasValue; 
     } 
    } 

    // Other non-relevant properties and methods 
} 

這些目標類:

public class DestinationPerson 
{ 
    public string Name { get; set; } 

    public DestinationAddress Address; 
} 

public class DestinationAddress 
{ 
    public string City { get; set; } 

    public string Country { get; set; } 
} 
+0

你看過'ConstructUsing'還是'ConvertUsing'? – pinkfloydx33

回答

2

無法找到常規的方式來設置轉換從MyLazyLoadingObject<T>T,然後T到一些TDestination沒有代碼重複。

但自定義IObjectMapper與一些手動表達構建實現這項工作。

下面是建立映射表達式類:

public class MyLazyLoadingObjectMapper : IObjectMapper 
{ 
    public bool IsMatch(TypePair context) 
    { 
     return context.SourceType.IsGenericType && context.SourceType.GetGenericTypeDefinition() == typeof(MyLazyLoadingObject<>); 
    } 

    public Expression MapExpression(TypeMapRegistry typeMapRegistry, IConfigurationProvider configurationProvider, PropertyMap propertyMap, Expression sourceExpression, Expression destExpression, Expression contextExpression) 
    { 
     var item = Expression.Property(sourceExpression, "Item"); 
     Expression result = item; 
     if (item.Type != destExpression.Type) 
     { 
      var typeMap = configurationProvider.ResolveTypeMap(item.Type, destExpression.Type); 
      result = Expression.Invoke(typeMap.MapExpression, item, destExpression, contextExpression); 
     } 
     // source != null && source.HasData ? result : default(TDestination) 
     return Expression.Condition(
      Expression.AndAlso(
       Expression.NotEqual(sourceExpression, Expression.Constant(null)), 
       Expression.Property(sourceExpression, "HasData") 
      ), 
      result, 
      Expression.Default(destExpression.Type) 
     ); 
    } 
} 

所有你需要的是將它註冊到MapperRegistry

AutoMapper.Mappers.MapperRegistry.Mappers.Add(new MyLazyLoadingObjectMapper()); 

當然,創造的常規類型的地圖(我猜你已經做到了):

cfg.CreateMap<SourceAddress, DestinationAddress>(); 
cfg.CreateMap<SourcePerson, DestinationPerson>(); 
+1

優秀的解決方案!它按預期工作。非常感謝你。 – Kilian

1

我已經取得了它這樣:

cfg.CreateMap<SourcePerson, DestinationPerson>().ForMember(t => t.Address, o => o.MapFrom(s => (s.Address.HasData)? s.Address.Item : null)); 
+1

我不喜歡的是我需要爲每個對象的每個MyLazyLoadingObject屬性重複相同的行(違反DRY原則!) – Kilian

相關問題