使用依赖注入实例化工作线程中的对象 [英] Instantiating an object in a worker thread with Dependency Injection

查看:90
本文介绍了使用依赖注入实例化工作线程中的对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

My objective is to run a never ending process in a parallel thread. The problem is, I cannot just instantiate my worker service in the new Thread, because I am using DI in my application.

基于我在SO上的研究,我注意到许多人建议将Abstract Factories注入线程中以动态实例化并行线程中的线程安全对象. 1 2

Based on my research here on SO, I have noticed many people are suggesting that Abstract Factories need to be injected into the thread to dynamically instantiate a thread-safe object in a parallel thread. 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的抽象工厂如下所示:

The Abstract Factory for IQueueProcessorFactory looks like this:

/// <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();
}

现在,我的主要问题是,实现IQueueProcessor的具体QueueProcessor有11个依赖项(我知道SRP代码的味道),每个依赖项本身都有5-6个依赖项.

Now, my main problem is, the concrete QueueProcessor that implements IQueueProcessor has 11 dependencies (I'm aware of the SRP code smell), and each dependency has 5-6 dependencies itself.

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

Does this mean I need ~60+ abstract factories in order to instantiate my IQueueProcessor in a worker thread? This sounds like a nightmare! Is there a better way or a more efficient way to achieve this?

推荐答案

这是否意味着我需要约60多个抽象工厂才能在工作线程中实例化IQueueProcessor?

最坏的情况下,这可能是必需的.当所有依赖项都必须具有瞬态生存期时(例如,当它们不是线程安全的时),就会发生这种情况.

In the worst case, that may be required. This can happen when all dependencies must have Transient lifetime - for example when they aren't thread-safe.

最佳情况下,所有这些依赖项都可能具有Singleton生存期,这可能适用于线程安全的依赖项.在这种情况下,不需要没有内部工厂:

In the best case, however, all those dependencies could have Singleton lifetime, which could be appropriate for thread-safe dependencies. In that case, no internal factories are required:

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依赖项混合在一起.

In reality, you may need to mix some Transient dependencies (that'd require factories) with some Singleton dependencies.

如果您最终需要数十家工厂,则可以考虑使用DI容器.其中一些可以自动生成工厂接口的实现-您只需提供他们必须实现的接口即可.

If you ultimately require dozens of factories, you could consider using a DI Container. Some of them can automatically generate implementations of factory interfaces - you only have to supply the interface they must implement.

此外,您不必为每个依赖项定义一个接口,但是可以考虑使用类似以下的通用接口:

Additionally, you don't have to define an interface for each dependency, but could consider instead using a generic interface like:

public interface IFactory<T>
{
    T Create();
}

同样,那里的一些DI容器也支持这种工厂.您也可以考虑完全放弃接口,而只使用像Func<T>这样的委托.

Again, some of the DI Containers out there support such factories. You could also consider entirely dispensing with an interface and just use a delegate like Func<T>.

除非情况特殊,否则,我不建议您使用DI容器,而是赞同

Unless the circumstances are special, however, I don't recommend a DI Container, but rather endorse Pure DI. When you use a DI Container, you lose compile-time safety, which I tend to think isn't worth the trade-off; after all, the bottleneck of programming is rarely your typing speed.

这篇关于使用依赖注入实例化工作线程中的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆