1

指定されたコマンドを実行して何かを実行するコマンドとコマンド実行クラスを持つプロジェクトがあります。

構造マップとジェネリックを使用して、システムで実行したい特定のコマンドのエクセクターのインスタンスを見つけて作成します。

例えば:

私は基本エグゼキュータクラスを持っています

public abstract class BaseExecutor<T> : IExecutor<T>
{
//do something
}

これは、次のコマンド クラスの構造マップによって作成する必要があるエグゼキュータの例です: MyFakeCommand

public class MyFakeCommandExecutor : BaseExecutor<MyFakeCommand>
{
    public void Run(MyFakeCommand cmd)
    {
        //do something
    }
}

エグゼキューターをコマンドに接続するには、ConnectImplementationsToTypesClosing を呼び出して構造マップを構成します。

public void RegisterExecutionAssembly<T>()
{
    IocContainer.Configure(c => c.Scan(scanner =>
    {
        scanner.AssemblyContainingType<T>();
        scanner.ConnectImplementationsToTypesClosing(typeof(IExecutor<>));
    }));
}

特定のコマンドのエグゼキュータを見つけるために、次のように呼び出します

public IExecutor<T> GetExecutorFor<T>()
{
    return IocContainer.GetAllInstances<IExecutor<T>>().FirstOrDefault(); 
}

したがって、コマンドのエグゼキューターを実行するには、次のようなことができます。

var cmd = new MyFakeCommand();
var executor = GetExecutorFor(cmd);
executor.Run(cmd);

コマンドを動的に作成し始めるまで、これはすべて正常に機能します。

例えば:

string commandTypeFullName = "Namespace.MyFakeCommand"
Type cmdType = Type.GetType(commandTypeFullName);

var cmd1 = JsonConvert.DeserializeObject(strCommand, cmdType);
var cmd2 = ObjectFactory.GetInstance(cmdType);

GetExecutorFor(cmd1); // fails to find executor
GetExecutorFor(cmd2); // fails to find executor

だから私の質問は、構造マップを構成して、動的にインスタンス化されたオブジェクトのエクセクターを見つけるにはどうすればよいですか?

4

2 に答える 2

1

すべてを実装する非ジェネリックIExecutorインターフェイスを導入する必要があります。IExecutor<T>

次に、ObjectFactory.ForGenericTypeメソッドを使用します。https://github.com/structuremap/structuremap/blob/v2.6.3/Source/StructureMap/ObjectFactory.cs#L310を参照してください。

var executor = ObjectFactory.ForGenericType(typeof(IExecutor<>)).
  WithParameters(cmdType).
  GetInstanceAs<IExecutor>()

executorこれで、非ジェネリックのインスタンスになりIExecutor、Run メソッドも持つ必要があります。Runエグゼキューターは、コマンド オブジェクトをキャストし、それをジェネリック メソッドに渡すことによって、非ジェネリック メソッドを実装しますRun

于 2013-04-15T14:31:09.303 に答える
0

StructureMap (SimpleInjector を使用) についてはわかりませんが、この質問はコンテナーに固有のものではなく、ジェネリックの問題です。

通常、dynamic キーワードを使用して、目的を達成できます。

//slight tweak to your listed method so that it would work
public IExecutor<T> GetExecutorFor<T>(T instance)
{
    return IocContainer.GetAllInstances<IExecutor<T>>().FirstOrDefault(); 
}

テストコード:

string commandTypeFullName = "Namespace.MyFakeCommand"
Type cmdType = Type.GetType(commandTypeFullName);

dynamic cmd1 = JsonConvert.DeserializeObject(strCommand, cmdType);
dynamic cmd2 = ObjectFactory.GetInstance(cmdType);

dynamic exec1 = GetExecutorFor(cmd1);
dynamic exec2 = GetExecutorFor(cmd2);

ベスト プラクティスは、ダイナミックの使用を制限することです。インテリセンスが提供されず、コンパイル時のサポートもありません。したがって、代わりにこれを使用します。

public void ExecuteCommand<T>(T command)
{
    IExecutor<T> executor = 
        IocContainer.GetAllInstances<IExecutor<T>>().FirstOrDefault(); 
    if (executor == null) throw new Exception();
    executor.Run(command)
}

テストコード:

string commandTypeFullName = "Namespace.MyFakeCommand"
Type cmdType = Type.GetType(commandTypeFullName);

dynamic cmd1 = JsonConvert.DeserializeObject(strCommand, cmdType);
dynamic cmd2 = ObjectFactory.GetInstance(cmdType);

ExecuteCommand(cmd1);
ExecuteCommand(cmd2);
于 2013-04-15T13:50:37.310 に答える