Multithreading Simpleinjector:当我有2个实现并且想要选择一个时,这是注册ManyForOpenGeneric的正确方法吗?

Multithreading Simpleinjector:当我有2个实现并且想要选择一个时,这是注册ManyForOpenGeneric的正确方法吗?,multithreading,asynchronous,dependency-injection,entity-framework-4.1,simple-injector,Multithreading,Asynchronous,Dependency Injection,Entity Framework 4.1,Simple Injector,使用简单的喷油器和喷油器。对于其中一个命令,我有两个处理程序实现。第一个是同步执行的“正常”实现: 公共类SendEmailMessageHandler :IHandleCommands { public SendEmailMessageHandler(IPProcessQueries查询处理器 ,ISendMail邮件发件人 ,ICommandEntities实体 ,i工作单元工作单元 ,iLogeExceptions exceptionLogger) { //将构造函数参数保存到私有只读字段

使用简单的喷油器和喷油器。对于其中一个命令,我有两个处理程序实现。第一个是同步执行的“正常”实现:

公共类SendEmailMessageHandler
:IHandleCommands
{
public SendEmailMessageHandler(IPProcessQueries查询处理器
,ISendMail邮件发件人
,ICommandEntities实体
,i工作单元工作单元
,iLogeExceptions exceptionLogger)
{
//将构造函数参数保存到私有只读字段
}
公共无效句柄(SendEmailMessageCommand)
{
var emailMessageEntity=GetThisFromQueryProcessor(命令);
var mailMessage=ConvertEntityToMailMessage(emailMessageEntity);
_mailssender.Send(mailMessage);
emailMessageEntity.SentOnUtc=DateTime.UtcNow;
_实体。更新(emailMessageEntity);
_unitOfWork.SaveChanges();
}
}
另一个类似于命令装饰器,但显式包装上一个类以在单独的线程中执行命令:

公共类SendAsyncEmailMessageHandler
:IHandleCommands
{
public SendAsyncEmailMessageHandler(ISendMail邮件发送者,
iLogeExceptions(例外日志)
{
//将构造函数参数保存到私有只读字段
}
公共无效句柄(SendEmailMessageCommand)
{
var program=新的SendAsyncEmailMessageProgram
(命令,_mailssender,_exceptionLogger);
var thread=新线程(program.Launch);
thread.Start();
}
私有类SendAsyncEmailMessageProgram
{
内部SendAsyncEmailMessage程序(
SendEmailMessageCommand命令
,ISendMail邮件发件人
,iLogeExceptions exceptionLogger)
{
//将构造函数参数保存到私有只读字段
}
内部无效启动()
{
//获取DbContext和查询处理器的新实例
var uow=MyServiceLocator.Current.GetService();
var qp=MyServiceLocator.Current.GetService();
var handler=新的SendEmailMessageHandler(qp,_mailSender,
uow作为ICommandEntities,uow,例外日志);
handler.Handle(_命令);
}
}
}
有一段时间simpleinjector对我大喊大叫,告诉我它发现了两个
iHandleCommand
的实现。我发现以下方法有效,但不确定这是否是最好的/最佳的方法。我想显式注册此接口以使用异步实现:

container.RegisterManyForOpenGeneric(typeof(iHandleCommand)),
(类型、实现)=>
{
//注册异步电子邮件处理程序
if(type==typeof(IHandleCommands))
Register(类型、实现)
.Single(i=>i==typeof(SendAsyncEmailMessageHandler));
else if(实现长度<1)
抛出新的InvalidOperationException(string.Format(
“找不到类型{0}的实现。”,
类型(名称));
else if(implementations.Length>1)
抛出新的InvalidOperationException(string.Format(
“{0}类型的实现数为{1}”。”,
type.Name、implementations.Length));
//注册单个实现(默认行为)
其他的
Register(type,implementations.Single());
},装配);
我的问题:这是正确的方法,还是有更好的方法?例如,我希望将SimpleInputer引发的现有异常重新用于所有其他实现,而不必在回调中显式抛出它们

更新对史蒂文答案的回复

我更新了我的问题,使之更加明确。我以这种方式实现它的原因是,作为操作的一部分,在成功发送
MailMessage
后,命令会更新数据库实体上名为
SentOnUtc
System.Nullable
属性

ICommandEntities
IUnitOfWork
都是由实体框架
DbContext
类实现的。
DbContext
根据http上下文注册,使用:

container.registerWebRequest();
Register(container.GetInstance);
Register(container.GetInstance);
Register(container.GetInstance);
simpleinjector wiki中的
RegisterWebRequest
扩展方法的默认行为是在
HttpContext
为空时注册一个临时实例(它将位于新启动的线程中)

var context=HttpContext.Current;
if(上下文==null)
{
//没有HttpContext:让我们创建一个瞬态对象。
返回_instanceCreator();
...
这就是为什么启动方法使用服务定位器模式获取
DbContext
的单个实例,然后将其直接传递给同步命令处理程序构造函数的原因两行要工作,必须使用相同的DbContext实例

注意:理想情况下,发送电子邮件应该由单独的轮询工作人员处理。此命令基本上是一个队列交换所。数据库中的EmailMessage实体已经拥有发送电子邮件所需的所有信息。此命令只需从数据库中获取一个未发送的邮件,发送它,然后记录邮件的日期时间操作。可以通过从不同的进程/应用程序轮询来执行此命令,但我不会接受此问题的答案。目前,当某种http请求事件触发此命令时,我们需要启动此命令。

确实存在easi