C#控制反转-获取所有实例化基类的类

C#控制反转-获取所有实例化基类的类,c#,inversion-of-control,C#,Inversion Of Control,我在一些程序中见过这个,但我不知道它叫什么。基本上,他们将参加各种课程: 第一类 类别2 类别3 每个类都有一个变量,可能称为顺序或步骤号: [IClassBaseRunner] public Class1 : IClassBase { public int step{ get { return 10; } } ... [IClassBaseRunner] public Class1 : IClassBase { public int step{ get { return 30

我在一些程序中见过这个,但我不知道它叫什么。基本上,他们将参加各种课程:

第一类

类别2

类别3

每个类都有一个变量,可能称为顺序或步骤号:

[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]。所有这些都在tact中,它将运行其所有组件,而无需单独实例化。他们将把每个类添加到一个列表中,并按顺序运行这些步骤。如果添加了步骤4,您所要做的就是在类的初始化上方添加一行,类似于名称空间中的,如下所示:

[IClassBaseRunner]
public Class4 : IClassBase
我不知道它叫什么,但如果有人有关于它的任何信息或搜索什么,那就太好了。这与控制和属性的反转有关


谢谢

我无法确定您所阐述的确切模式,但它似乎至少属于基本战略模式

基于您提到的在包含新类时不需要实例化类或添加boostraping代码。。。这是一个好的依赖注入库和基于约定的策略可以帮助解决的问题。加上某种组装扫描,您应该很少需要处理配置组件的问题

下面是一个使用Ninject和Ninject约定扩展(Nuget包Ninject.extensions.Conventions)实现这一点的示例。正如您的问题所示,本例不需要任何属性装饰器,但如果需要,您可以创建并使用它们

此外,Structure Map和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!");  
    }
}

我不能肯定你所阐述的确切模式,但它似乎至少属于基本战略模式

基于您提到的在包含新类时不需要实例化类或添加boostraping代码。。。这是一个好的依赖注入库和基于约定的策略可以帮助解决的问题。加上某种组装扫描,您应该很少需要处理配置组件的问题

下面是一个使用Ninject和Ninject约定扩展(Nuget包Ninject.extensions.Conventions)实现这一点的示例。正如您的问题所示,本例不需要任何属性装饰器,但如果需要,您可以创建并使用它们

此外,Structure Map和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!");  
    }
}
好吧,你可以搜索“依赖注入”来寻找startWell,你可以搜索“依赖注入”作为开始