2012-05-10 13 views
2

OKアプリケーションにコマンドオブジェクトをキューに追加するCommand-CommandHandlerパターンを実装しました。 Castle Windsorを介して依存性注入を使用して汎用メソッドとともにコマンドオブジェクトの関連ハンドラを取得します。ジェネリックス経由でインターフェイスの代わりにクラスタイプを渡す

コマンドインタフェースはとても似空白である:CommandHandlerインタフェースは、同じように扱う一方で

public interface ICommand 
{ 
} 

public interface ICommandHandler<TCommand> where TCommand : ICommand 
{ 
    void Handle(TCommand command); 
} 

これらは、その後、私はキューを介して送信したいコマンドによって実現されています。そして、そのようなDependencyRegistrationラッパーを通じて城ウィンザーに登録:

_dependencyRegister 
    .AddRegistration<ICommandHandler<TestCommand>, TestCommandHandler>(); 

だから、キューに追加される各コマンドは、ハンドラと1対1でマッピングします。その後Castle Windsorに登録されます。私たちは、特定のCommandオブジェクトに関連するCommandHandlerを取得するには、このような一般的な方法を使用することができます。

private void HandleCommand<T>(T queueItem) where T: ICommand 
{ 
    var handler = _dependencyResolver.Resolve<ICommandHandler<T>>(); 

    handler.Handle(queueItem); 
} 

最後のピースは、このようになりますキューディスパッチャ方法である:

private void DispatchQueueItem(ICommand queueItem) 
{ 
    HandleCommand(queueItem); 
} 

右。問題は、私がICommandとしてキューからコマンドを取り出し、それをDispatchQueueItemメソッドに渡すときです。 HandleCommandメソッドに送信されるとき、 "T"型は常に "ICommand"インタフェースに設定されます。インターフェイス(DependencyRegistrationサンプルコードのTestCommand)の実際の実装ではなく、

私の質問は、 HandleCommandメソッドを実装のTypeを取得するように設定するにはどうすればよいですか。インターフェイスではない?

+0

私はこの一般的な設定を複製するのに1秒です。私は 'DispatchQueueItem'ボックスが' ICommand'であるので、 'HandleCommand'の包括的な引数はボックス型から推測されていると思います。 – Tejs

+0

(T)汎用構文は、そのタイプのコンパイル時の解決です。実行時の型の解決を探しています。それを判断するには、ダイナミックタイプまたはリフレクションを使用する必要があります。 – user957902

答えて

4

変更ジェネリックへのご発送方法:あなたがC#のを強制することができ

private void DispatchQueueItem<T>(T queueItem) 
    where T: ICommand 
{ 
    HandleCommand(queueItem); 
} 

UPDATEが実行時に

private static void DispatchQueueItem(ICommand queueItem) 
{ 
    HandleCommand((dynamic)queueItem); 
} 
+0

+1、これは基本的に私が提案しようとしていたものです。 – Tejs

+0

OKジェネリックを使用するように呼び出しメソッドを変更しました。しかし私はまだ問題を抱えています。それが助けになるならば。 DispatchQueueItemメソッドに渡す前にICommandアイテムを取得するメソッドは次のようになります: 'public IEnumerable Dequeue()' –

+0

あなたは凡例の7つの陰影です。つまり、動的ではなく、実装された型に解決するために項目を使用します –

0

私はあなたがそれはインターフェースのなりたいと思う - しかし、あなたはただそこに定義されたメソッド契約持っている必要があります - などを:

public interface ICommand 
{ 
    void Execute(); 
} 

//Concrete implementation: 
public TestCommand : ICommand 
{ 
    public void Execute() 
    { 
     //Do something 
    } 
} 

その後、あなたはDIのうちのICommandを取得するときに - queueItem.Execute()と呼ぶことができます。これはあなたが割り当てた具体的な実装を参照します。

+1

フェアポイント;しかし、ここで概説したCommand - CommandHandlerパターンの完全性を維持したいと思います:http://www.cuttingedge.it/blogs/steven/pivot/entry.php?id=91。あなたが記述した方法は確かに簡単です。上記の記事はなぜ分離が有用であるかを説明するはずです。 –

0

YoutのキューはディスパッチICommandsをlalwaysますこの方法でオブジェクト型を定義します。だから、 "フードの下に"タイプを取得する必要があります:

private void HandleCommand<T>(T queueItem) where T: ICommand 
{ 
    var typeParam = queueItem.GetType(); 
    var type = typeof(ICommandHandler<>).MakeGenericType(typeParam); 
    var handler = _dependencyResolver.Resolve(type); 

私は正確なsintaxについては分かりません。手に城ウィンザーとのプロジェクトはありません。

+0

私たちはそこに近づいているように見えます。しかし、 '.Resolve(type)'または 'Resolve 'または 'Resolve >'を追加すると "シンボル 'type'を解決できません" –

+0

どのタイプが 'type'ですか?つまり、 'type.FullName'を取得します。また、 'queueItem'の型です。 – JotaBe

関連する問題