2015-07-19 75 views
1

有幾個程序我見過,但我不確定我知道它叫什麼。從本質上講,他們將採取各種類:C#控制反轉 - 獲取實例化基類的所有類

Class1的

的Class2

Class3的

這些類具有可變也許叫做順序或步數:

[IClassBaseRunner] 
public Class1 : IClassBase 
{ 
    public int step{ get { return 10; } } 
... 

[IClassBaseRunner] 
public Class1 : IClassBase 
{ 
    public int step{ get { return 30; } } 
... 

[IClassBaseRunner] 
public Class1 : IClassBase 
{ 
    public int step{ get { return 20; } } 
... 

所有這些類都是IClassBase之類的接口的一部分。現在,他們可以做一些他們不需要初始化任何類的東西,但是每個類都必須在類的聲明之上有一個屬性,例如[IClassBaseRunner]。所有這些都可以實現,它將運行它們的所有組件,而不需要單獨實例化。他們會將每個類添加到列表中,然後按順序執行這些步驟。如果添加了第4步,所有你所要做的就是添加一行類的初始化上面,有點像它在命名空間,如下所示:

[IClassBaseRunner] 
public Class4 : IClassBase 

我不知道其所謂的,但是如果有人有任何關於它的信息或要搜索什麼,那就太好了。它與控制和屬性的倒置有關。

謝謝!

+0

好了,你可以搜索 「依賴注入」 的一個開始 –

回答

0

我不能肯定你正在說明的確切模式,但它似乎至少落入基本策略模式。

根據您提到的無需實例化類或在包含新類時添加boostraping代碼...這是一種良好的依賴注入庫和基於約定的策略可以提供的幫助。添加某種程序集掃描,你幾乎不必處理配置組件。

下面是使用Ninject和Ninject慣例擴展(Nuget package ninject.extensions.conventions)可以實現的一個例子。這個例子並不需要你的問題所示的任何屬性裝飾器,但是如果你需要的話,你可以創建和使用它們。

此外,結構圖和MEF是其他流行的依賴注入庫,您可以嘗試使用並查看哪些最適合您。

static IKernel kernel = new StandardKernel(); 
void Main() 
{ 
    // 
    // Automatic binding using 
    // Ninject.Extensions.Conventions 
    // Generally, you only want to declare your 
    // DI container once in the application lifetime 
    // Expecially in web apps, you will also need to 
    // consider the scope of bound classes, such as: 
    // Transient, Thread, Singleton, or Request 
    kernel.Bind(x=>x 
     .FromThisAssembly() 
     .SelectAllClasses() 
     .BindAllInterfaces() 
    ); 
    // 
    // Now we can resolve the loader and run it 
    // Compare this code to how it would look if you 
    // manually instantiate all the dependencies and consider: 
    // - How much additional code is there? 
    // - How easy is it to perform unit tests on the various 
    // components (Mocking is useful here)? 
    // - What is the effort if I need to swap out a service 
    // such as IMessageWriter? 
    // 
    // IMPORTANT: For example only. Do not use kernel.Get() 
    // all over your code base. 
    // This results in a ServiceLocator anti-pattern! 
    ProcessRunner runner = kernel.Get<ProcessRunner>(); 
    runner.Execute(); 
} 

public interface IMessageWriter{ 
    void Write(string message); 
} 

public class MessageWriter : IMessageWriter 
{ 
    public void Write(string message){ 
     Console.WriteLine ("MESSAGE: {0}", message); 
    } 
} 

public interface IProcessStep { 
    int Step{ get; } 
    void Execute(); 
} 

public class ProcessRunner 
{ 
    private readonly IEnumerable<IProcessStep> steps; 
    public ProcessRunner(IEnumerable<IProcessStep> steps) 
    { 
     this.steps = steps;  
    } 

    public void Execute(){ 
     steps 
      .OrderBy (o => o.Step) 
      .ToList() 
      .ForEach(i=>i.Execute()); 
    } 
} 
public class ProcessStep1 : IProcessStep 
{ 
    private readonly IMessageWriter writer; 
    public ProcessStep1(IMessageWriter writer) 
    { 
     this.writer = writer;  
    } 
    public int Step { get { return 10; }} 
    public void Execute(){ 
     writer.Write("Hello from step1!");  
    } 
} 
public class ProcessStep2 : IProcessStep 
{ 
    private readonly IMessageWriter writer; 
    public ProcessStep2(IMessageWriter writer) 
    { 
     this.writer = writer;  
    } 
    public int Step { get { return 20; }} 
    public void Execute(){ 
     writer.Write("Hello from step2!"); 
    } 
} 
public class ProcessStep3 : IProcessStep 
{ 
    private readonly IMessageWriter writer; 
    public ProcessStep3(IMessageWriter writer) 
    { 
     this.writer = writer;  
    } 
    public int Step { get { return 30; }} 
    public void Execute(){ 
     writer.Write("Hello from step3!"); 
    } 
} 

輸出

MESSAGE: Hello from step1! 
MESSAGE: Hello from step2! 
MESSAGE: Hello from step3!