Is it a good practice to pass the Ninject kernel around?

北城以北 提交于 2019-12-06 11:00:02

In such cases I usually use a Factory pattern. In the scheduler you can have the task factory as a dependency. This factory can also have multiple methods for creating different types of tasks.

class DDPSchedulerTaskFactory : IDDPSchedulerTaskFactory
{
    DDPSchedulerTaskFactory(ILogger logger, List<string> platforms, IBackOfficeDataStore backOfficeDataStore, ICommonDataStore commonDataStore)
    {
        _logger = logger;
        _platforms = platforms;
        _backOfficeDataStore = backOfficeDataStore;
        _commonDataStore = commonDataStore;
    }

    public IDDPSchedulerTask CreateNormal(){
        return new DDPSchedulerTask(
            _logger,
            _platforms,
            _backOfficeDataStore,
            _commonDataStore);
    }

    public IDDPSchedulerTask CreateSpecial(someAdditionalParameter){
        return new AnotherDDPSchedulerTask(
            _logger,
            _platforms,
            _backOfficeDataStore,
            _commonDataStore,
            someAdditionalParameter);
    }

    public IDDPSchedulerTask CreateTaskWithDifferentDependenties(yetAnotherParameter){
        return new AnotherDDPSchedulerTask(
            _logger,
            _platforms,
            yetAnotherParameter);
    }
}

Than in your scheduler you can add tasks like that:

class Scheduler{
    IDDPSchedulerTaskFactory _taskFactory;
    public Scheduler(IDDPSchedulerTaskFactory taskFactory){
        _taskFactory = taskFactory; // factory gets all the needed dependencies for all tasks from DI
    }   
    ...

    public void ConfigureTasks(){
        _tasks.Add(_taskFactory.CreateNormal());
        _tasks.Add(_taskFactory.CreateSpecial("Some important message"));
        _tasks.Add(_taskFactory.CreateTaskWithDifferentDependenties(123));
    }
}

You should take advantage of Ninject.Extensions.Factory.

Just create an interface that represents your tasks factory. Then pass information to Ninject that is a factory And he would create for you full implementations of this interface.

using System;
using System.Collections.Generic;
using Ninject;
using Ninject.Extensions.Factory;

internal class Program
{
    public static void Main(string[] args)
    {
        IKernel ninjectKernel = new StandardKernel();

        ninjectKernel.Bind<DDPSchedulerTask>().ToSelf();
        ninjectKernel.Bind<AWNFileGeneratorTask>().ToSelf();
        ninjectKernel.Bind<IDirectoryResolver>().To<DirectoryResolver>();
        ninjectKernel.Bind<ITaskFactory>().ToFactory();

        var mainTask = ninjectKernel.Get<DDPSchedulerTask>();
        mainTask.CreateDbSchedulerTask();
        mainTask.CreateAwnFileTask();

        Console.ReadLine();
    }
}

public interface ITaskFactory
{
    TTask CreateTask<TTask>() where TTask : DDPSchedulerTask;
}

public class DDPSchedulerTask
{
    private readonly ITaskFactory _tasksFactory;
    private readonly List<DDPSchedulerTask> _tasksList;

    public DDPSchedulerTask(ITaskFactory tasksFactory)
    {
        _tasksFactory = tasksFactory;

        _tasksList = new List<DDPSchedulerTask>();
    }

    public void CreateAwnFileTask()
    {
        var task = _tasksFactory.CreateTask<AWNFileGeneratorTask>();
        _tasksList.Add(task);
    }

    public void CreateDbSchedulerTask()
    {
        var task = _tasksFactory.CreateTask<DDPSchedulerTask>();
        _tasksList.Add(task);
    }
}

public class AWNFileGeneratorTask : DDPSchedulerTask
{
    [Inject]
    public IDirectoryResolver DirectoryResolver { get; set; }

    public AWNFileGeneratorTask(ITaskFactory tasksFactory)
        : base(tasksFactory)
    {
    }
}

public interface IDirectoryResolver
{
}

public class DirectoryResolver : IDirectoryResolver
{
}

@gisek As noted Giseke dependency injection via property is not the best solution. You can also use a constructor injection in this example.

public class AWNFileGeneratorTask : DDPSchedulerTask
{
    private IDirectoryResolver _directoryResolver;

    public AWNFileGeneratorTask(ITaskFactory tasksFactory, IDirectoryResolver directoryResolver)
        : base(tasksFactory)
    {
        _directoryResolver = directoryResolver;
    }
}

Extra params injection:

public interface ITaskFactory
{
    DDPSchedulerTask CreateDDPSchedulerTask();
    AWNFileGeneratorTask CreateAWNFileGeneratorTask(string extraParam);
}

public class AWNFileGeneratorTask : DDPSchedulerTask
{
    private IDirectoryResolver _directoryResolver;
    private string _extraParam;

    public AWNFileGeneratorTask(ITaskFactory tasksFactory, IDirectoryResolver directoryResolver,
        string extraParam)
        : base(tasksFactory)
    {
        _extraParam = extraParam;
        _directoryResolver = directoryResolver;
    }
}

public void CreateAwnFileTask()
{
    var task = _tasksFactory.CreateAWNFileGeneratorTask("extra");
    _tasksList.Add(task);
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!