晚上好, 我正试图在中型项目中首次使用DI实现SOLID原理。 大部分时间我都明白,但现在我遇到了麻烦。 让我举一个可怜的例子,但它显示了应用程序的结构。 我继承了具有不同构造函数的类(下面提供的代码)。当我需要一个实例时,我知道我需要的课程。 那么,关于这段代码的2个问题: 1 /在这种情况下我是否必须使用接口来实现SOLID原理(或者在Program.cs中简单地声明ClassA的实例,如ClassA exemple = new ClassA(“text”)) 2 /做得好吗? (什么是好/什么是坏,做什么/要避免什么?)
class Program
{
static void Main(string[] args)
{
IFactory exemple = new Factory();
//With Unity--> exemple=Resolve<IFactory>();
exemple.GetTextClassA("test");
exemple.GetTextClassB(1);
Console.ReadLine();
}
}
public interface IFactory
{
ClassA GetTextClassA(string text);
ClassB GetTextClassB(int text);
}
public class Factory : IFactory
{
public ClassA GetTextClassA(string text)
{
return new ClassA(text);
}
public ClassB GetTextClassB(int text)
{
return new ClassB(text);
}
}
public abstract class MainClass
{
private string _text;
public MainClass(){}
protected abstract string GetText();
protected virtual void Initialize()
{
_text = GetText();
Console.WriteLine(_text);
}
public string TextToDisplay
{
get { return _text; }
}
}
public class ClassA : MainClass
{
string _textA;
public ClassA(string textParam)
{
_textA = textParam;
base.Initialize();
}
protected override string GetText()
{
return "Text is :"+_textA;
}
}
public class ClassB : MainClass
{
int _numParam;
public ClassB(int numParam)
{
_numParam = numParam;
base.Initialize();
}
protected override string GetText()
{
return "Text is :" + _numParam.ToString();
}
}
非常感谢您的评论。
答案 0 :(得分:2)
您似乎没有注入任何依赖项。
DI的最低要求需要两件事:
一个非常基本的例子
interface IServiceA
{
void Foo();
}
interface IServiceB
{
void Bar();
}
class ServiceA : IServiceA
{
public void Foo() { do something ; }
}
class ServiceB : IServiceB
{
public void Bar() { do something else; }
}
interface IProgram
{
void Execute();
}
class Program : IProgram
{
private readonly IServiceA _serviceA;
private readonly IServiceB _serviceB;
public Program(IServiceA serviceA, IServiceB serviceB)
{
_serviceA = serviceA; //Injected dependency
_serviceB = serviceB; //Injected dependency
}
public void Execute()
{
_serviceA.Foo();
_serviceB.Bar();
}
}
void Main()
{
//Composition root
var container = new UnityContainer();
container.RegisterType<IServiceA, ServiceA>();
container.RegisterType<IServiceB, ServiceB>();
container.RegisterType<IProgram, Program>();
//The one and only one entry point for Program
container.Resolve<IProgram>().Execute();
}
这里发生了什么?
Program
是你的主要课程。但它也没有做任何事情。在SRP下,它将有趣的职责卸载到其他类(ServiceA
和ServiceB
)。只有它不知道类是什么 - 只需要它所需的接口。它不知道它们来自何处,或者它们是如何被创造出来的。它们就在那里,因为在创建Program
时它们被推(注入)。
Unity容器的设置注册了Program
所需的所有接口。它会通过构造函数参数将依赖项注入Program
(Unity会自动为您执行此操作)。然后程序可以调用服务来完成工作,再次,不知道它们来自哪里。
为什么我们这样做?有几个原因
测试程序可以创建实现IServiceA
和IServiceB
的其他类(存根)。通过注入这些存根的依赖关系,测试可以只关注Program
中的逻辑。
通过将特定接口放置为构造函数参数,可以立即明确Program
所依赖的内容。如果你得到错误的接口,程序甚至不会编译。这比等待运行时找到你需要的服务不可用要好得多(这就是为什么我们不注入Unity容器本身 - 你不能告诉接口Program
将会是什么尝试拉而不读取所有代码。与Service Locator pattern或简单的静态工厂相同。
通过使用容器注入依赖项,您还允许依赖项具有依赖项(例如,如果ServiceA
依赖于ServiceC
)。 Unity容器也会注入注入的类,k并注入注入的类,依此类推。
您可以管理组合根中的生命周期(每个请求,每个线程或每个进程),因为这是责任所在。您不希望对象生命周期逻辑分散在整个代码库中,因为这使得在每个用户的线程与服务或Windows应用程序(具有不同的生命周期规则)的应用程序域中运行相同的对象非常困难。