我的目标是在并行线程中运行一个永无止境的进程。问题是,我不能在新线程中实例化我的工作服务,因为我在我的应用程序中使用了DI。
基于我在SO上的研究,我注意到很多人都建议将抽象工厂注入线程,以在并行线程中动态实例化线程安全对象。 1,2
/// <summary>
/// Responsible for starting parallel long running worker threads
/// </summary>
public class ParallelWorkerStarter
{
private readonly IQueueProcessorFactory _queueProcessorFactory;
public ParallelWorkerStarter(IQueueProcessorFactory queueProcessorFactory)
{
_queueProcessorFactory = queueProcessorFactory;
}
public void StartQueueProcessorThread()
{
queueProcessor = new Thread(
() =>
{
_queueProcessorFactory.Create().ProcessQueue();
})
{ Name = "QueueProcessor" };
queueProcessor.Start();
}
}
IQueueProcessorFactory
的抽象工厂看起来像这样:
/// <summary>
/// Abstract factory responsible for producing an <see cref="IQueueProcessor"/>
/// </summary>
/// <remarks>
/// This abstract factory is used to generate an <see cref="IQueueProcessor"/> In a seperate thread.
/// Therefore, all of its dependencies also need to be dynamically generated
/// </remarks>
public interface IQueueProcessorFactory
{
/// <summary>
/// Dynamically creates ab <see cref="IQueueProcessor"/>
/// </summary>
/// <returns>
/// The <see cref="IQueueProcessor"/>.
/// </returns>
IQueueProcessor Create();
}
现在,我的主要问题是,实现QueueProcessor
的具体IQueueProcessor
有11个依赖项(我知道SRP代码的气味),每个依赖项本身有5-6个依赖项
/// <inheritdoc />
public class QueueProcessorFactory : IQueueProcessorFactory
{
private readonly IEventTriggerQueuedEventServiceFactory _qeueuedEventServiceFactory;
private readonly ILoggerFactory _loggerFactory;
private readonly IEventTriggerActionGroupLogServiceFactory _eventTriggerActionGroupLogServiceFactory;
private readonly IExceptionLogServiceFactory _exceptionLogServiceFactory;
private readonly IEventTriggerServiceFactory _eventTriggerServiceFactory;
private readonly IConditionServiceFactory _conditionServiceFactory;
private readonly IEventTriggerActionServiceFactory _eventTriggerActionServiceFactory;
private readonly IEngineEnabledCheckerFactory _engineEnabledCheckerFactory;
private readonly IEventTriggerScheduleSetServiceFactory _eventTriggerScheduleSetServiceFactory;
private readonly IEventTriggerActionResultServiceFactory _eventTriggerActionResultServiceFactory;
private readonly IWorkflowExceptionHandlerFactory _workflowExceptionHandlerFactory;
public QueueProcessorFactory(
IEventTriggerQueuedEventServiceFactory qeueuedEventServiceFactory,
ILoggerFactory loggerFactory,
IEventTriggerActionGroupLogServiceFactory eventTriggerActionGroupLogServiceFactory,
IExceptionLogServiceFactory exceptionLogServiceFactory,
IEventTriggerServiceFactory eventTriggerServiceFactory,
IConditionServiceFactory conditionServiceFactory,
IEventTriggerActionServiceFactory eventTriggerActionServiceFactory,
IEngineEnabledCheckerFactory engineEnabledCheckerFactory,
IEventTriggerScheduleSetServiceFactory eventTriggerScheduleSetServiceFactory,
IEventTriggerActionResultServiceFactory eventTriggerActionResultServiceFactory,
IWorkflowExceptionHandlerFactory workflowExceptionHandlerFactory)
{
_qeueuedEventServiceFactory = qeueuedEventServiceFactory;
_loggerFactory = loggerFactory;
_eventTriggerActionGroupLogServiceFactory = eventTriggerActionGroupLogServiceFactory;
_exceptionLogServiceFactory = exceptionLogServiceFactory;
_eventTriggerServiceFactory = eventTriggerServiceFactory;
_conditionServiceFactory = conditionServiceFactory;
_eventTriggerActionServiceFactory = eventTriggerActionServiceFactory;
_engineEnabledCheckerFactory = engineEnabledCheckerFactory;
_eventTriggerScheduleSetServiceFactory = eventTriggerScheduleSetServiceFactory;
_eventTriggerActionResultServiceFactory = eventTriggerActionResultServiceFactory;
_workflowExceptionHandlerFactory = workflowExceptionHandlerFactory;
}
/// <inheritdoc />
public IQueueProcessor Create()
{
return new QueueProcessor(
_qeueuedEventServiceFactory.Create(),
_loggerFactory.Create(),
_eventTriggerActionGroupLogServiceFactory.Create(),
_exceptionLogServiceFactory.Create(),
_eventTriggerServiceFactory.Create(),
_conditionServiceFactory.Create(),
_eventTriggerActionServiceFactory.Create(),
_engineEnabledCheckerFactory.Create(),
_eventTriggerScheduleSetServiceFactory.Create(),
_eventTriggerActionResultServiceFactory.Create(),
_workflowExceptionHandlerFactory.Create());
}
}
这是否意味着我需要~60 +抽象工厂才能在工作线程中实例化我的IQueueProcessor
?这听起来像是一场噩梦!是否有更好的方法或更有效的方法来实现这一目标?
答案 0 :(得分:2)
这是否意味着我需要~60 +抽象工厂才能在工作线程中实例化我的
IQueueProcessor
?
在最坏情况中,可能需要这样做。当所有依赖项必须具有Transient生存期时,例如当它们不是线程安全的时候,就会发生这种情况。
但是,在最佳情况中,所有这些依赖项都可能具有Singleton生存期,这可能适用于线程安全依赖项。在这种情况下,没有内部工厂是必需的:
public class QueueProcessorFactory : IQueueProcessorFactory
{
private readonly IEventTriggerQueuedEventService _qeueuedEventService;
private readonly ILogger _logger;
private readonly IEventTriggerActionGroupLogService _eventTriggerActionGroupLogService;
// etc...
public QueueProcessorFactory(
IEventTriggerQueuedEventService qeueuedEventService,
ILogger logger,
IEventTriggerActionGroupLogService eventTriggerActionGroupLogService,
/* etc... */)
{
_qeueuedEventService = qeueuedEventService;
_logger = logger;
_eventTriggerActionGroupLogService = eventTriggerActionGroupLogService;
// etc...
}
public IQueueProcessor Create()
{
return new QueueProcessor(
_qeueuedEventService,
_logger,
_eventTriggerActionGroupLogService,
/* etc... */);
}
}
实际上,您可能需要将一些Transient依赖项(需要工厂)与一些Singleton依赖项混合使用。
如果您最终需要数十家工厂,可以考虑使用DI容器。其中一些可以自动生成工厂接口的实现 - 您只需提供他们必须实现的接口。
此外,您不必为每个依赖项定义接口,但可以考虑使用通用接口,如:
public interface IFactory<T>
{
T Create();
}
同样,一些DI容器支持这样的工厂。您还可以考虑完全取消界面,只需使用Func<T>
等代表。
但是,除非情况特殊,否则我不建议使用DI容器,而是赞同Pure DI。当你使用DI容器时,你会失去编译时的安全性,我倾向于认为不值得权衡;毕竟,编程的瓶颈很少是你的打字速度。