2015-05-29 110 views
2

我在写一个执行几个任务的小框架。 有些任务需要通过Ninject注入的特定属性。传递Ninject内核是否是一个好习惯?

比方说,我在我的基类下面的构造表示单个任务:

protected DDPSchedulerTask(ILogger logger, List<string> platforms, IBackOfficeDataStore backOfficeDataStore, ICommonDataStore commonDataStore) 
{ 
    _logger = logger; 
    _platforms = platforms; 
    _backOfficeDataStore = backOfficeDataStore; 
    _commonDataStore = commonDataStore; 
} 

所需的所有任务,这些属性,所以我使用Ninject用以下Ninject模块注入其中。

public class DDPDependencyInjectionBindingConfiguration : NinjectModule 
{ 
    #region NinjectModule Members 

    /// <summary> 
    ///  Loads the module into the kernel. 
    /// </summary> 
    public override void Load() 
    { 
     Bind<Scheduler>().ToSelf(); // Make sure that the 'Scheduler' is resolved to itself. 
     Bind<ILogger>().ToMethod(context => LogFactory.Create()); // Make sure that an instance of an ILogger is created through the LogFactory. 

     // Straightforward binding. 
     Bind<ICommonDataStore>().To<Common>(); 
     Bind<IBackOfficeDataStore>().To<BtDbInteract>(); 
     Bind<IDirectoryResolver>().To<Demo>(); 
    } 

    #endregion 
} 

我的调度对象本身如果需要由Ninject解决链中的第一个条目,所以我这个手动解决通过Ninject。现在

var schedulerInstance = kernel.Get<Scheduler>(); 

,我有调度这增加了任务列表的方法,所以无法使用Ninject:

var tasksList = new List<DDPSchedulerTask> 
{ 
    new AWNFileGeneratorTask(_logger, availablePlatforms, _backOfficeDataStore, _commonDataStore) 
}; 

然后,正在执行所有这些任务。 现在,其中一些任务确实需要额外的依赖关系,我想通过Ninject来解决这些问题,但我应该如何执行此操作?

在任务中,我创建了一个属性Inject属性,但对象保留空值。

[Inject] 
private IDirectoryResolver directoryResolver { get; set; } 

任何人都有关于如何解决这个问题的想法?

我可以将内核传递给不同的任务,但有些东西告诉我这不是正确的方法。

亲切的问候

回答

3

在这种情况下,我通常使用工厂模式。在调度程序中,您可以将任务工厂作为依赖项。这个工厂也可以有多种创建不同类型任务的方法。

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

不是在您的调度,您可以添加任务,这样的:

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)); 
    } 
} 
+0

好的事,但在你的代码是不正确的。在你的create方法中,返回类型被设置为“DDPSchedulerTask”,但你要返回一个“DDPSchedulerTaskFactory”。另外,你能否解释一下你的解决方案?我应该从哪里调用create方法,因为我希望Unity的其他属性也可以被注入。 – Complexity

+0

@Complexity是的,只是纠正它 – gisek

+0

感谢您的更正。你介意从我需要调用这个工厂的地方展示我,因为我想继续使用Ninject来确保依赖注入。我没有看到Ninject在这里的胶水。我仍然需要传入'someAdditionalParameters',我想让Ninject内核来解决这个问题。 – Complexity

4

你应该好好Ninject.Extensions.Factory优势。

只需创建一个代表您的任务工厂的界面。然后将信息传递给作为工厂的Ninject,并且他会为您创建此接口的完整实现。

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 如上所述Giseke依赖注入经由属性是不是最好的解决方案。在这个例子中你也可以使用构造器注入。

public class AWNFileGeneratorTask : DDPSchedulerTask 
{ 
    private IDirectoryResolver _directoryResolver; 

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

额外参数注:

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); 
} 
+0

然而,这种方式你必须绑定到Ninject - 无法轻松替换IOC容器。 (浅谈注入属性) – gisek

+0

构造函数注入IDirectoryResolver没有问题。它也应该工作。例如:public AWNFileGeneratorTask(ITaskFactory tasksFactory,IDirectoryResolver directoryResolver):base(tasksFactory) –

+0

好的。以及如何将其他参数(不依赖)传递给任务构造函数? – gisek

相关问题