仅具有基类的依赖注入示例
是否可以在没有任何第三方工具的情况下进行 DI?我读到过人们在发现一些 DI 框架之前使用抽象类和接口来实现这一点。 ID 是如何以这种非常基本的形式完成的?
Is it possible to do DI without any third party tools? I've read about people doing it with an abstract class and interface before they discovered some DI framework. How is ID done in that very basic form?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
只需在实例化该类时将依赖项传递给该类的构造函数即可。当项目很小(低于几千行代码)时,不需要 DI 框架 - 您可以编写一个工厂并手动连接所有依赖项。
Just pass the dependencies to the constructor of the class when you instantiate it. No DI frameworks are needed when the project is small (below a couple of thousand lines of code) - you can write a factory and wire up all the dependencies manually.
当然,无需第三方工具也是可以的。简单示例:
SomeClass
将ILogger
作为构造函数中的输入。它用它来记录一些输出。假设我们希望它出现在控制台中:在某些代码中:
..但是我们希望将日志记录在文件中:
因此,我们改为注入文件记录器:
SomeClass
很高兴不知道ILogger
正在使用实现,并且只使用注入的实现。通常最好让工厂创建接口实现的实例,而不是在整个代码中构造对象,以便更轻松地更改正在使用的实现。Of course it's possible without third-party tools. Simple sample:
SomeClass
takes anILogger
as input in the constructor. It uses it for logging some output. Let's say we want it in the console:In some code:
..but then we want the log in a file instead:
So, we inject the file logger instead:
SomeClass
is happily unaware of theILogger
implementation in use, and just uses whichever implementation that is injected. It's usually a good idea to have a factory creating the instances of the interface implementations instead of having the objects constructed all over the code, in order to make it simpler to change the implementation in use.本教程中有一个很好的描述。
基本上,您所做的就是让
DependingClass
仅了解Interface
,然后使用IndependentClass
实现该接口。通过构造函数重载,您可以让单元测试框架发送模拟对象。一些代码可能会让我更容易理解我的意思:
现在,如您所见,我们提供了一个默认的类类型,如果没有向构造函数提供参数,它将被实例化。但我们也允许注入实现相同接口的不同类,或者相同接口的模拟对象。
编辑:正如评论中所指出的,在较大的应用程序中最好有一个实例化 DependingClass 的工厂,并删除“默认”构造函数。这样,如果您决定更改实现,则只需更改一个地方。
There is a nice description in this tutorial.
Basically what you do is that you let the
DependingClass
only know about anInterface
, and then you implement that interface with yourIndependentClass
. With constructor overloads, you let for example a unit testing framework send in a mock object.Some code might make it easier to understand what I'm getting at:
Now, as you see, we have provided a default class type that will be instantiated if no argument is provided to the constructor. But we have also allowed for injection of a different class that implements the same interface, or a mock object of the same.
EDIT: As pointed out in a comment, it is probably better in a larger app to have a factory that instantiates the
DependingClass
, and remove the "default" constructor. That way you only have to change in one place if you decide to change the implementation.您可以创建通过接口相互通信的组件,并让托管程序实例化这些组件并将它们链接在一起。
这将是您的解决方案结构:
一个 dll 程序集,它定义组件(接口 + 属于接口方法签名一部分的数据对象)之间的契约。
定义您的组件(实现接口)的一个或多个 dll 程序集。组件之间的任何通信都是通过接口完成的。
一个 exe 程序集,用于启动托管进程、实例化组件并通过设置某些属性来链接它们。每当您需要替换一个组件时,您只需要更改此项目。
您可以为任何组件创建单元测试,模拟您正在测试的组件所使用的组件。
您还可以从托管项目中的 app.confing 文件中读取属性绑定。
You can create your components communicating with each other through interfaces and have your hosting program that instantiates the components and link them together.
This would be your solution structure:
An dll assembly that defines the contract between components (interfaces + data objects that are part of the interface methods signatures).
One ore more dll assemblies that defines your components (that implement interfaces). Any communication between components is done through interfaces.
An exe assembly that starts up the hosting process, instantiates the components and link them setting some properties. Whenever you need to substitute one component you only need to change this project.
You can create unit tests for any of your components mocking up the components that are used by the component you are testing.
Also you can get fancy reading the property bindings from the app.confing file in the hosting project.
您可以通过三种方法来做到这一点...
在构造函数中传递对依赖实例(当然是实现接口的类的实例)的引用。
创建新对象,然后通过属性设置器将引用传递给依赖对象
在对象中使用接受引用并将其分配给您为此创建的内部provbate变量
There are three ways you can do it...
Pass the reference to the dependant instance (which is an instance of a class that implements the interface of course) in the constructor.
Create the new object and then pass the reference to the dependant object via a property setter
Use a function within the object that accepts the reference and assigns it to the internal provbate variable you have created for this