C# 如何使用Simple Injector从中介发送调用
我有以下情况:C# 如何使用Simple Injector从中介发送调用,c#,generics,dependency-injection,simple-injector,C#,Generics,Dependency Injection,Simple Injector,我有以下情况: public interface ICommand { } public interface ICommandHandler<TCommand> where TCommand : ICommand { void Handle(TCommand command); } public interface ISepsCommandHandler<TCommand> : ICommandHandler<TCommand> where
public interface ICommand { }
public interface ICommandHandler<TCommand> where TCommand : ICommand
{
void Handle(TCommand command);
}
public interface ISepsCommandHandler<TCommand> : ICommandHandler<TCommand>
where TCommand : ICommand
{
event EventHandler<EntityExecutionLoggingEventArgs> UseCaseExecutionProcessing;
}
public sealed class CalculateNewAverageElectricEnergyProductionPriceCommandHandler
: BaseCommandHandler,
ISepsCommandHandler<CalculateNewAverageElectricEnergyProductionPriceCommand>
{ ... }
public sealed class CalculateCpiCommandHandler
: BaseCommandHandler, ISepsCommandHandler<CalculateNewConsumerPriceIndexCommand>
{ ... }
问题:
我想将ICommandHandler
的集合解析为CqrsMediator
的构造函数。我试过各种方法
问题:
为什么这在SI中不起作用
var bla = GetAllInstances(typeof(ICommandHandler<ICommand>));
var bla=GetAllInstances(typeof(ICommandHandler));
我收到一条消息,它找不到ICommandHandler
,但注册了ICommandHandler
,尽管我在泛型中给出了一个约束,即TCommand只能是ICommand类型
有人能帮助构建和的中介模式吗
为什么这在SI中不起作用
var bla = GetAllInstances(typeof(ICommandHandler<ICommand>));
这与在.NET中不起作用的原因相同。只有当ICommandHandler
接口定义为协变时,这才有效,但这是不可能的,因为TCommand
是一个输入参数
让我们暂时从图片中删除DI容器。使用简单的旧C#代码,您希望实现以下目标:
ICommandHandler handler1=new Command1Handler();
ICommandHandler handler2=新的Command2Handler();
ICommandHandler handler3=新命令3 Handler();
IEnumerable handlers=new[]{handler1,handler2,handler3};
新的CqrsMediator(处理程序);
前面的代码段创建了三个新的命令处理程序:
实现Command1Handler
ICommandHandler
实现Command2Handler
ICommandHandler
实现Command3Handler
ICommandHandler
CqrsMediator
,所以需要将它们放入ICommandHandler
类型的变量中。通过这种方式,您可以轻松构建一个数组(ICommandHandler[]
),该数组可以注入到CqrsMediator
但是,此代码不会编译。C#编译器将声明以下内容:
错误CS0266:无法将类型“Command1Handler”隐式转换为“ICommandHandler”。存在显式转换(是否缺少强制转换?)
这就是你问题的根源。例如,您的命令处理程序不能从ICommandHandler
强制转换为ICommandHandler
。要理解这一点,您需要了解协方差和逆变换。你可能想开始
要允许ICommandHandler
可分配给ICommandHandler
它要求ICommandHandler
抽象是协变的:
Send
方法设置为泛型不是一个选项,则也可以在Send
方法中使用反射来查找命令的正确类型:公共类CqrsMediator:ICqrsMediator
{
专用只读容器;
公共CqrsMediator(Container Container)=>this.Container=Container;
公共无效发送(TCommand命令)
{
var handlerType=typeof(ICommandHandler).MakeGenericType(command.GetType());
动态处理程序=container.GetInstance(handlerType);
返回handler.Handle((动态)命令);
}
}
在这两种情况下,您都让
CqrsMediator
实现依赖于容器。这意味着实施成为基础设施的组成部分;它成为你生活的一部分。谢谢你,史蒂文!但是,是否可以将ICommandHandler集合注入CqrsMediator的构造函数,而不是容器或任何其他非容器的形式?如果您的CqrsMediator
不是泛型的,您将如何注入TCommand
?你不能。您需要容器(或某种可以创建任意随机处理程序的工厂)来完成这项工作。
public interface ICommandHandler<out TCommand> where TCommand : ICommand { ... }