2017-11-22 7 views
1

システムオブジェクトのリストを変換し、私のオブジェクトは、次のようになります。Automapperは、私は別の使用automapperに1つのクラスを変換する必要が

public class Foo 
{ 
    public List<object> Objects { get; set; } 
} 


public class Bar 
{ 
    public List<object> Objects { get; set; } 
} 

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

public class BarItem 
{ 
    public string Name { get; set; } 
} 
項目のためのより多くの種類だけでなく、 FooItemBarItemが、私はちょうど使用があるかもしれません

これら2つは単純化のために、私はこの設計をする必要があります。

私はタイプコンバータなどのようないくつかのことを試みましたが、まだ運がありません。ここで

現在の基本的な変換コード

Mapper.Initialize(cfg => 
{ 
    cfg.CreateMap<FooItem, BarItem>(); 
    cfg.CreateMap<Foo, Bar>(); 
}); 

var foo = new Foo() 
{ 
    Objects = new List<object>() { new FooItem() { Name = "name" } } 
}; 

var map = Mapper.Map<Foo, Bar>(foo); 

目標はBarオブジェクトは、実行時にBarItemsのリストが含まれていることですが、これまでのところ、私は、実行時にのみFooItemのリストを取得するだけで管理しています。

アイデア?

答えて

2

BarItemsのリストのみに満足していますか?

var map = Mapper.Map<IEnumerable<FooItem>, List<BarItem>>(foo.Objects.Cast<FooItem>()); 

更新:あなたはこのようにそれを行うことができます。この場合、あなたはこのようにそれを行うことができます。 >オブジェクトが他のすべてに優先します - マップオブジェクトがあるため、

cfg.CreateMap<object, object>() 
    .ConstructUsing(src => { 
     if (src is FooItem) { 
      return Mapper.Map<BarItem>(src); 
     } 
     // ... 
     throw new InvalidOperationException($"Can not map source item of type '{src.GetType().FullName}'."); 
    }); 

しかし、あなたはおそらくObjectsコレクション内の項目のためのインターフェースを導入する必要があります。

class Program 
{ 
    static void Main(string[] args) 
    { 
     Mapper.Initialize(cfg => 
     { 
      cfg.CreateMap<FooItem, BarItem>(); 
      cfg.CreateMap<Foo, Bar>() 
      .ForMember(dest => dest.Objects, opt => opt.ResolveUsing<CustomResolver>()); 

     }); 
     Mapper.AssertConfigurationIsValid(); 
     var foo = new Foo() 
     { 
      Objects = new List<object>() { new FooItem() { Name = "name" } } 
     }; 

     //var map = Mapper.Map<IEnumerable<FooItem>, List<BarItem>>(foo.Objects.Cast<FooItem>()); 
     var map = Mapper.Map<Foo, Bar>(foo); 
    } 
} 

public class CustomResolver : IValueResolver<Foo, Bar, List<object>> 
{ 
    public List<object> Resolve(Foo source, Bar destination, List<object> member, ResolutionContext context) 
    { 
     var map = Mapper.Map<IEnumerable<FooItem>, List<BarItem>>(source.Objects.Cast<FooItem>()); 
     return map.Cast<object>().ToList(); 
    } 
} 
+0

automapperない構成するときに現在...ように

ヌルを認識しません。そして、私は単純化のための項目のみを含むが、このリストには、より多くの種類を含めることができます。 – ogomrub

+0

@ogomrub Ok、作業アップデートを追加しました。この場合、異なるタイプの 'CustomResolver'が必要になります。 – Ogglas

+2

これまでのところ私が見つけた最高のものです。私は受け入れられたとマークした。私はより多くの型を扱うためにOfTypeへのキャストを修正しなければならなかった。御時間ありがとうございます。 – ogomrub

2

あなたはConstructUsing句内の型チェックを行うことができますFooItem - > BarItemマップを使用したいと考えています。

+0

Thx、残念ながら私はインターフェイスを導入することはできませんし、この悪いデザインでスタックする必要があります。 – ogomrub

+0

次に、Ogglasのカスタムリゾルバが提案されています。 –

0

@Ogglasに触発されて、私はすべてのタイプをチェックする必要がない興味深い解決策を見つけ出すことができました。

基本的に私は書いた私のITypeConverter

public class CustomResolver : ITypeConverter<List<object>, List<object>> 
{ 
    public List<object> Convert(List<object> source, List<object> destination, ResolutionContext context) 
    { 
     var objects = new List<object>(); 

     foreach (var obj in source) 
     { 
      var destinationType = context.ConfigurationProvider.GetAllTypeMaps().First(x => x.SourceType == obj.GetType()).DestinationType; 
      var target = context.Mapper.Map(obj, obj.GetType(), destinationType); 
      objects.Add(target); 
     } 

     return objects; 
    } 
} 

そして自身の文脈から、各タイプのための適切なマッピングを取得します。残念ながら

Mapper.Initialize(cfg => 
{ 
    cfg.CreateMap<FooItem, BarItem>(); 
    cfg.CreateMap<List<object>, List<object>>().ConvertUsing<CustomResolver>(); 
    cfg.CreateMap<Foo, Bar>(); 
});