2016-06-15 10 views
5

次のマッピングを使用して、データオブジェクトをviewmodelオブジェクトにマップしています。C#Automapperカスタムリゾルバからプロパティを使用して解決する方法

ObjectMapper.cs

public static class ObjectMapper 
{ 
    public static void Configure() 
    { 
     Mapper.CreateMap<User, UserViewModel>() 
      .ForMember(dest => dest.Title, 
         opt => opt.ResolveUsing<TitleValueResolver>()) 
      .ForMember(dest => dest.Name, 
         opt => opt.ResolveUsing<NameValueResolver >()) 
      .ForMember(dest => dest.ShortName, 
         opt => opt.ResolveUsing<ShortNameValueResolver >());   
    } 
} 

パーサ私は別のカスタム値を使用して宛先プロパティにロジックを追加するために上記のコードを使用しています

public class Parser{ 
public string GetTitle(string title){ 
/* add some logic */ 
return title; 
} 
public string GetName(string title){ 
/* add some logic */ 
return name; 
} 
public string GetShortName(string title){ 
/* add some logic */ 
return shortname; 
} 
} 

AutoMapperCustomResolvers.cs

public class TitleValueResolver : ValueResolver<User, string> 
{ 
    private readonly BaseValueResolver _baseResolver; 
    public TitleValueResolver() 
    { 
     _baseResolver = new BaseValueResolver(); 
    } 

    protected override string ResolveCore(Usersource) 
    { 
     return _baseResolver.Parser.GetTitle(source.TITLE); 
    } 
} 

public class NameValueResolver : ValueResolver<User, string> 
{ 
    private readonly BaseValueResolver _baseResolver; 
    public NameValueResolver() 
    { 
     _baseResolver = new BaseValueResolver(); 
    } 

    protected override string ResolveCore(Usersource) 
    { 
     return _baseResolver.Parser.GetName(source.TITLE); 
    } 
} 

public class ShortNameValueResolver : ValueResolver<User, string> 
{ 
    private readonly BaseValueResolver _baseResolver; 
    public ShortNameValueResolver() 
    { 
     _baseResolver = new BaseValueResolver(); 
    } 

    protected override string ResolveCore(Usersource) 
    { 
     return _baseResolver.Parser.GetShortName(source.TITLE); 
    } 
} 

リゾルバ。これが正しいアプローチであるかどうかはわかりません。

i)これを達成するより良い方法はありますか?

ii)そして、カスタムリゾルバコンストラクタに依存関係を注入したい場合に、unityを使って解決する方法は?

おかげ

+0

'TitleValueResolver'はどのように構築されると思いますか?これにはデフォルトのコンストラクタはなく、マッピング設定に 'ConstructedBy'式を指定しないでください。一般的に、あなたの例では、クラスがひどく欠けています...不足している部分を減らしたり提供したりして、例をmvceに変えてください。 – grek40

+0

@ grek40、私は私の質問を更新しました。 –

+0

'TypeValueResolver'は新しい' TitleValueResolver'ですか? 'MAMAsset'が' User'型から何かを解決するためのバリューリゾルバを期待していますか? – grek40

答えて

0

、私はあなたの質問を理解しているように、あなたがValueResolverを利用したい、それが複数のターゲットのプロパティを解決するために使用される中間データオブジェクトの中に複数のソースプロパティを解決します。例として、私は次のソース、ターゲット、中間およびリゾルバのタイプを想定しています

// source 
class User 
{ 
    public string UserTitle { get; set; } 
} 

// target 
class UserViewModel 
{ 
    public string VM_Title { get; set; } 

    public string VM_OtherValue { get; set; } 
} 

// intermediate from ValueResolver 
class UserTitleParserResult 
{ 
    public string TransferTitle { get; set; } 
} 

class TypeValueResolver : ValueResolver<User, UserTitleParserResult> 
{ 
    protected override UserTitleParserResult ResolveCore(User source) 
    { 
     return new UserTitleParserResult { TransferTitle = source.UserTitle }; 
    } 
} 

あなたはopt.ResolveUsing<TypeValueResolver>()を利用するためにターゲットプロパティを必要としています。つまり、適切なターゲットプロパティが利用可能なマッピングを確立することができます。

ので、一瞬のために、適切なコンテナ型に結果をラップすることができます:

class Container<TType> 
{ 
    public TType Value { get; set; } 
} 

とマッピング

Mapper.CreateMap<User, Container<UserViewModel>>() 
    .ForMember(d => d.Value, c => c.ResolveUsing<TypeValueResolver>()); 

そして、別のマッピング

Mapper.CreateMap<UserTitleParserResult, UserViewModel>() 
    .ForMember(d => d.VM_Title, c => c.MapFrom(s => s.TransferTitle)) 
    .ForMember(d => d.VM_OtherValue, c => c.Ignore()); 

そして、別のものを作成しますマッピング

Mapper.CreateMap<User, UserViewModel>() 
    .BeforeMap((s, d) => 
    { 
     Mapper.Map<User, Container<UserViewModel>>(s, new Container<UserViewModel> { Value = d }); 
    }) 
    .ForAllMembers(c => c.Ignore()); 
// establish more rules for properties... 

最後のマッピングは、別個に設定されたマッピングルールを使用してソースからの値で宛先を更新するために、ネストされたマッピングに依存するため、少し特殊です。実際のマップされたタイプのBeforeMapに適切な中間マッピングと呼び出しを追加することによって、さまざまなプロパティに対して複数の異なる転送マッピングを持つことができます。これがあなたを助けている場合

var user = new User() { UserTitle = "User 1" }; 

// create by mapping 
UserViewModel vm1 = Mapper.Map<UserViewModel>(user); 

UserViewModel vm2 = new UserViewModel() { VM_Title = "Title 2", VM_OtherValue = "Value 2" }; 
// map source properties into existing target 
Mapper.Map(user, vm2); 

知らん:AutoMapperはBeforeMap

小の使用例でのマッピングについて知らないので、他のマッピングで処理されるプロパティは、無視する必要があります。解決策と思われるものではなく、最初の問題を説明するために質問を言い換えると、より良い方法があるかもしれません。

+0

私は自分の質問を更新しました。今はっきりすることを願っています。 –

+0

申し訳ありませんが、Unityは私の対象外です。まだ使用していません。 – grek40

+0

こんにちは、基本的に私は複数のターゲットプロパティを解決する中間オブジェクトに1つの単一のソースプロパティを解決するValueResolverを使用しようとしています。 –

関連する問題