2015-05-29 107 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

相關問題