Inversion of control 动态实例化对象时,如何将实现连接到structuremap中的关闭类型

Inversion of control 动态实例化对象时,如何将实现连接到structuremap中的关闭类型,inversion-of-control,structuremap,Inversion Of Control,Structuremap,我有一个项目,它有commands和commandexecutors类,它们接受给定的命令并做一些事情 我使用structuremap和泛型为我想要在系统中运行的任何给定命令查找和创建执行器的实例 例如: string commandTypeFullName = "Namespace.MyFakeCommand" Type cmdType = Type.GetType(commandTypeFullName); var cmd1 = JsonConvert.DeserializeObject(

我有一个项目,它有commands和commandexecutors类,它们接受给定的命令并做一些事情

我使用structuremap和泛型为我想要在系统中运行的任何给定命令查找和创建执行器的实例

例如:

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
我有一个基本的executor类

public abstract class BaseExecutor<T> : IExecutor<T>
{
//do something
}
这一切都很好,直到我开始动态创建命令

例如:

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

因此,我的问题是如何配置结构映射以仍然找到动态实例化对象的执行器?

我不知道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(); 
}
最佳实践应该是限制动态的使用-它不提供智能感知,没有编译时支持等。因此,我将改为:

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

我不知道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(); 
}
最佳实践应该是限制动态的使用-它不提供智能感知,没有编译时支持等。因此,我将改为:

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

您需要引入一个非通用的
IExecutor
接口,所有的
IExecutor
都要实现这个接口

然后使用
ObjectFactory.ForGenericType
方法。看

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

现在,
executor
将是非泛型
IExecutor
的一个实例,它也应该有一个Run方法。执行器通过强制转换命令对象并将其传递给泛型
Run
方法来实现非泛型
Run
方法。

您需要引入一个非泛型
IExecutor
接口,所有
IExecutor
都实现该接口

然后使用
ObjectFactory.ForGenericType
方法。看

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

现在,
executor
将是非泛型
IExecutor
的一个实例,它也应该有一个Run方法。执行器通过强制转换command对象并将其传递给generic
Run
方法来实现非generic
Run
方法。

这是绝对可以做到的(无需使用dynamic关键字)-但我现在无法运行代码进行调试。
cmd2
变量包含什么内容?这绝对是可以做到的(无需使用dynamic关键字)-但我现在无法运行代码进行调试。
cmd2
变量包含什么?哦,我明白了,您的解决方案解决了我的问题!它确实需要额外的非泛型run方法,但我肯定可以使用它。谢谢你应该将其标记为答案,以便其他人知道问题已得到回答(无需点击阅读评论)。哦,我明白了,你的解决方案解决了我的问题!它确实需要额外的非泛型run方法,但我肯定可以使用它。谢谢您您应该将其标记为答案,以便其他人知道问题已被回答(无需点击阅读评论)。
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);
var executor = ObjectFactory.ForGenericType(typeof(IExecutor<>)).
  WithParameters(cmdType).
  GetInstanceAs<IExecutor>()