2011-08-05 23 views
0

私は2つのコンストラクタを持つ必要があるコマンドクラスを持っています。しかし、 構造マップを使用すると、1つのコンストラクタしか指定できないようです。 を使用します。私は現在、特定の コマンド・クラスをサブタイプ化することによって問題を解決しました。各コマンド・クラスは、それ自身の実装では、 インターフェースおよびコンストラクターです。以下のコードのように。 ISelectCommandは 文字列コンストラクタとintコンストラクタの2つの個別のインターフェイスを実装しています。これは の2つのサブタイプをstructuremapを使用して登録するためのものです。構造体のコンストラクタオーバーロード

しかし、これはハックだと私は考えていますが、コンストラクタのパラメータとして渡された 型によってコンストラクタシグネチャを解決するためにstructuremapが可能でないのはなぜですか?次に、SelectProductCommandを に登録し、ISelectCommandとして をインスタンス化します。 ObjectFactury.With(10).Use>(); orObjectFactury.With( "testproduct")。>();を使用します。

public class SelectProductCommand : ISelectCommand<IProduct>, 
ICommand, IExecutable 
{ 
    private readonly Func<Product, Boolean> _selector; 
    private IEnumerable<IProduct> _resultList; 

    public SelectProductCommand(Func<Product, Boolean> selector) 
    { 
     _selector = selector; 
    } 

    public IEnumerable<IProduct> Result 
    { 
     get { return _resultList; } 
    } 

    public void Execute(GenFormDataContext context) 
    { 
     _resultList = GetProductRepository().Fetch(context, 
_selector); 
    } 

    private Repository<IProduct, Product> GetProductRepository() 
    { 
     return ObjectFactory.GetInstance<Repository<IProduct, 
Product>>(); 
    } 
} 

public class SelectProductIntCommand: SelectProductCommand 
{ 
    public SelectProductIntCommand(Int32 id): base(x => 
x.ProductId == id) {} 
} 

public class SelectProductStringCommand: SelectProductCommand 
{ 
    public SelectProductStringCommand(String name): base(x => 
x.ProductName.Contains(name)) {} 
} 

p.s.私は構造体マップに使用するコンストラクタマップを指定する方法を知っていますが、私の考え方は、コンストラクタに渡されたパラメータに基づいて適切なコンストラクタを選択する方法があるかどうかです(つまり、通常のメソッドオーバーロードを使用します)。

答えて

1

を使用し、お使いのコントローラ/プレゼンターに直接repositoresを使用しています。このクラスは、ObjectFactoryから具体的な型を取得し、この型を使用して、ファクトリメソッドの過去のパラメータに従ってインスタンスを構築します。今私はObjectFactoryを使ってCommandFactoryのインスタンスを作成します。 CommandFactoryの実装は別の解決策であるため、「クライアントソリューション」は「サーバー」ソリューションとは独立しています。ここで

public class CommandFactory 
{ 

    public ICommand Create<T>() 
    { 
     return Create<T>(new object[] {}); 
    } 

    public ICommand Create<T>(object arg1) 
    { 
     return Create<T>(new[] {arg1}); 
    } 

    public ICommand Create<T>(object arg1, object arg2) 
    { 
     return Create<T>(new[] {arg1, arg2}); 
    } 

    public ICommand Create<T>(object arg1, object arg2, object arg3) 
    { 
     return Create<T>(new[] {arg1, arg2, arg3}); 
    } 

    public ICommand Create<T>(object[] arguments) 
    { 
     return (ICommand)Activator.CreateInstance(GetRegisteredType<T>(), arguments); 
    } 

    public static Type GetRegisteredType<T>() 
    { 
     return ObjectFactory.Model.DefaultTypeFor(typeof (T)); 
    } 
} 
1

短い答えはthis post by the creator of Structuremapです。

長い答えは、あなたがそのコードにある構造に関するものです。私の見解では、コマンドは定義上、「エンティティ」に対して何かを行う「クラス」です。つまり、何らかの形でクラスを変更します。 CreateNewProductCommandを考えてください。

私が間違っていない場合、ここではクエリにコマンドを使用しています。あなたはまた、ここに浮かぶ懸念の問題を少し浮かべています。コマンドは、私はコマンドを構築したい方法としてCreateProductCommandを使用することで何をするかを定義し、どのようにそれを行うには、かなりになると、あなたは

private Repository<IProduct, Product> GetProductRepository() 
{ 
    return ObjectFactory.GetInstance<Repository<IProduct, Product>>(); 
} 

で使用しているサービスの場所のようなものを取得する投稿しましたつまり、製品情報などのデータのみが含まれています。 次に、IHandles<CreateProductCommand>を実装するCreateProductCommandHandlerを1つのメソッドHandleまたはExecuteで作成します。そうすることで、懸念とテスト容易性の分離が向上します。クエリの一部については

、ちょうどその代わりに私は小さなユーティリティクラスを使用して問題を解決したと思わQuery Object pattern

+0

あなたはコマンド/ハンドラに軌道に乗るためにいくつかのリンクです: http://lostechies.com/jimmybogard/2010/01/07/advanced-structuremap-custom-registration-conventions-for-partially-閉鎖型/ http://lostechies.com/derickbailey/2008/11/20/ptom-command-and-conquer-your-uoucing-problems/ – Henning

+0

申し訳ありませんが、これは私が探していた答えではありませんために。私はあなたがジェレミー・ミラーによって言及した投稿を知っています。しかし、私が言及したように、これはあらかじめ特定のコンストラクタを指定することにのみ関係します。コマンドパターンに関するあなたのコメントについては、ありがとう、私はそれを調べます。しかし、コマンド・クラス(ネーミングが適切でないかもしれない)が、リポジトリから製品をフェッチするためのselectメソッドのラッパーに過ぎないことを認識する必要があります。私はまた、挿入、削除、更新コマンドを持っています。この設定の目的は、トランザクションマネージャに渡されるコマンドのリストにこれらを追加できるということです。 – halcwb