使用依赖注入实例化工作线程中的对象

时间:2018-05-02 14:49:20

标签: c# .net multithreading dependency-injection abstract-factory

我的目标是在并行线程中运行一个永无止境的进程。问题是,我不能在新线程中实例化我的工作服务,因为我在我的应用程序中使用了DI。

基于我在SO上的研究,我注意到很多人都建议将抽象工厂注入线程,以在并行线程中动态实例化线程安全对象。 12

/// <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?这听起来像是一场噩梦!是否有更好的方法或更有效的方法来实现这一目标?

1 个答案:

答案 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容器时,你会失去编译时的安全性,我倾向于认为不值得权衡;毕竟,编程的瓶颈很少是你的打字速度。