c#控制反转-获取所有实例化基类的类
本文关键字:实例化 基类 获取 控制 | 更新日期: 2023-09-27 18:03:27
我在一些程序中见过这个,但我不确定我知道它叫什么。基本上,他们会选择各种各样的课程:
Class1
Class2
Class3
这些类中的每一个都有一个变量,可能称为order或step number:
[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
我不确定它叫什么,但如果有人有任何关于它的信息或要搜索什么,那就太好了。这与控制和属性的反转有关。
谢谢!
我不能肯定地说你所描绘的确切模式,但它似乎至少属于基本策略模式。
基于你提到的不需要实例化类或添加引导代码,当你包含新的类…这是一个好的依赖注入库和基于约定的策略可以帮助解决的问题。添加某种类型的组装扫描,您应该很少需要处理配置组件的问题。
下面是一个如何使用Ninject和Ninject Conventions扩展(Nuget package 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!");
}
}
输出MESSAGE: Hello from step1!
MESSAGE: Hello from step2!
MESSAGE: Hello from step3!