如果我们想利用依赖注入,我们还应该创建实例吗?
Should we still create instances if we want to take advantage of dependency injection?
我对依赖注入的概念越来越深入,阅读的越多,我就越喜欢它背后的想法。我已经使用它一段时间了,但时不时还有很多事情让我感到困惑,我觉得我没有充分发挥它的潜力。
想象一下下面的代码。在这个 class 中,(可能有一些事情可以改进但是..)我们有一个方法 returns 一个字符串值。不需要构造函数注入(或者至少我是这么认为的,如果我错了请纠正我),但是在 try 块的最后一行,我们创建了新的实例StreamReader class 能够将响应流传递给它并使用 ReadToEnd 方法获取结果。
依赖注入背后的想法是避免在 class 中创建实例,但如何处理这种情况?
public class WebClientService : IWebClientService
{
public async Task<String> GetApiResponseAsync(string Url)
{
String responseText = await Task.Run(() =>
{
try
{
HttpWebRequest request = WebRequest.Create(Url) as HttpWebRequest;
WebResponse response = request.GetResponse();
Stream responseStream = response.GetResponseStream();
return new StreamReader(responseStream).ReadToEnd();
}
catch (Exception e)
{
LogMessageDispatcher.Instance.Log(e);
}
return null;
});
return responseText;
}
}
我正在复习“Mark Seemann 的书 - 依赖注入”,但我还有很多内容要讲。
这是一个非常简单的示例,并且相对容易定义,因为您的耦合是一个基本的 Class,没有任何与服务相关的功能。我们先从维基百科中DI的定义说起:
In software engineering, dependency injection is a technique whereby one object supplies the dependencies of another object. A "dependency" is an object that can be used, for example as a service. Instead of a client specifying which service it will use, something tells the client what service to use. The "injection" refers to the passing of a dependency (a service) into the object (a client) that would use it. The service is made part of the client's state.[1] Passing the service to the client, rather than allowing a client to build or find the service, is the fundamental requirement of the pattern.
虽然这是什么意思。当我们使用 DI 时,我们不应该创建一个 StringBuilder
对象吗?答案是否定的(或者更好但并非总是如此)。我可以在没有 DI 的情况下创建一个新的浮动吗?创建构建器服务并从那里创建 StreamReader 是否有意义?
你会看到 StreamReader
是一个非常基本的实现 public class StreamReader : System.IO.TextReader
而 classes 甚至没有实现除 IDisposable 之外的任何其他接口。您不能认真考虑在任何 class.
中为 IDisposable 注入 StreamReader
如果您想与 StreamReader
分离,那么这意味着您将来可能想使用其他东西。您可以创建一个 StreamService
并根据需要创建您的流,但最终 StreamService
将具有耦合,因为 StreamReader
无法注入。
这就是维基百科推断服务被注入的原因。对象可能是解耦的,但您可能想使用其他模式,例如 Factory.
顺便说一句,使用 StreamReader
时,请始终使用 Using
关键字,以便可以正确处理对象。
依赖注入在某些方面很强大
测试:解耦对于单元测试至关重要,DI 是实现这一点的好方法,因此您可以拥有一个接口和多个实现,并根据您的需要为您的代码编写单元测试并注入特定的混凝土 class.
控制对象创建:它让您可以控制(具体)对象的创建方式以及对象的生命周期。
所以你一开始就得知道
- 您想 centralize/control 创建什么类型的 class 对象和接口?
- 如果将来发生任何更改,您希望您的代码在没有大的更改的情况下继续工作的功能是什么?
- 在您的情况下,您使用的是 StreamReader,它是 C# 中的内置 class,因此您必须考虑我将在我的代码中使用多少次 class?以后还需要改吗?
如果我是你,我会考虑两个选择
我不关心 StreamReader,它是 C# 中的内置 class,它运行良好,我不打算编写单元测试来测试 StreamReader 功能,所以我会像您在代码示例中那样使用它。
我在代码中的很多地方都使用了 StreamReader,而且我有一些重复的逻辑,每次读取流后我都会这样做,所以我将使用我想要的主要方法创建 IStreamReader 接口使用然后使用DI注入具体实现。
注意:在使用 DI 时,您不会在系统中注入所有对象。
The idea behind Dependency Injection is to avoid creating instances inside a class, but how to deal with this scenario?
这根本不是重点。 DI 的中心点之一是启用 松散耦合 到 易失性依赖关系 。并非 class 所依赖的所有类型都是 volatile。有些是 稳定的 并且没有必要阻止在 class 中创建稳定的依赖项。两者的第一章 Dependency Injection in .NET (by Mark Seemann) and its successor Dependency Injection Principles, Practices, and Patterns (by Mark and I) have a detailed description of what Volatile Dependencies and Stable Dependencies 是什么以及它们有何不同。
您应该问的主要问题是 WebClientService
所依赖的任何类型是否为易失性依赖项。答案取决于你的特定上下文,你应该能够在(重新)阅读第 1 章后弄明白这一点。本章可以在线免费阅读。
我对依赖注入的概念越来越深入,阅读的越多,我就越喜欢它背后的想法。我已经使用它一段时间了,但时不时还有很多事情让我感到困惑,我觉得我没有充分发挥它的潜力。
想象一下下面的代码。在这个 class 中,(可能有一些事情可以改进但是..)我们有一个方法 returns 一个字符串值。不需要构造函数注入(或者至少我是这么认为的,如果我错了请纠正我),但是在 try 块的最后一行,我们创建了新的实例StreamReader class 能够将响应流传递给它并使用 ReadToEnd 方法获取结果。
依赖注入背后的想法是避免在 class 中创建实例,但如何处理这种情况?
public class WebClientService : IWebClientService
{
public async Task<String> GetApiResponseAsync(string Url)
{
String responseText = await Task.Run(() =>
{
try
{
HttpWebRequest request = WebRequest.Create(Url) as HttpWebRequest;
WebResponse response = request.GetResponse();
Stream responseStream = response.GetResponseStream();
return new StreamReader(responseStream).ReadToEnd();
}
catch (Exception e)
{
LogMessageDispatcher.Instance.Log(e);
}
return null;
});
return responseText;
}
}
我正在复习“Mark Seemann 的书 - 依赖注入”,但我还有很多内容要讲。
这是一个非常简单的示例,并且相对容易定义,因为您的耦合是一个基本的 Class,没有任何与服务相关的功能。我们先从维基百科中DI的定义说起:
In software engineering, dependency injection is a technique whereby one object supplies the dependencies of another object. A "dependency" is an object that can be used, for example as a service. Instead of a client specifying which service it will use, something tells the client what service to use. The "injection" refers to the passing of a dependency (a service) into the object (a client) that would use it. The service is made part of the client's state.[1] Passing the service to the client, rather than allowing a client to build or find the service, is the fundamental requirement of the pattern.
虽然这是什么意思。当我们使用 DI 时,我们不应该创建一个 StringBuilder
对象吗?答案是否定的(或者更好但并非总是如此)。我可以在没有 DI 的情况下创建一个新的浮动吗?创建构建器服务并从那里创建 StreamReader 是否有意义?
你会看到 StreamReader
是一个非常基本的实现 public class StreamReader : System.IO.TextReader
而 classes 甚至没有实现除 IDisposable 之外的任何其他接口。您不能认真考虑在任何 class.
如果您想与 StreamReader
分离,那么这意味着您将来可能想使用其他东西。您可以创建一个 StreamService
并根据需要创建您的流,但最终 StreamService
将具有耦合,因为 StreamReader
无法注入。
这就是维基百科推断服务被注入的原因。对象可能是解耦的,但您可能想使用其他模式,例如 Factory.
顺便说一句,使用 StreamReader
时,请始终使用 Using
关键字,以便可以正确处理对象。
依赖注入在某些方面很强大
测试:解耦对于单元测试至关重要,DI 是实现这一点的好方法,因此您可以拥有一个接口和多个实现,并根据您的需要为您的代码编写单元测试并注入特定的混凝土 class.
控制对象创建:它让您可以控制(具体)对象的创建方式以及对象的生命周期。
所以你一开始就得知道
- 您想 centralize/control 创建什么类型的 class 对象和接口?
- 如果将来发生任何更改,您希望您的代码在没有大的更改的情况下继续工作的功能是什么?
- 在您的情况下,您使用的是 StreamReader,它是 C# 中的内置 class,因此您必须考虑我将在我的代码中使用多少次 class?以后还需要改吗?
如果我是你,我会考虑两个选择
我不关心 StreamReader,它是 C# 中的内置 class,它运行良好,我不打算编写单元测试来测试 StreamReader 功能,所以我会像您在代码示例中那样使用它。
我在代码中的很多地方都使用了 StreamReader,而且我有一些重复的逻辑,每次读取流后我都会这样做,所以我将使用我想要的主要方法创建 IStreamReader 接口使用然后使用DI注入具体实现。
注意:在使用 DI 时,您不会在系统中注入所有对象。
The idea behind Dependency Injection is to avoid creating instances inside a class, but how to deal with this scenario?
这根本不是重点。 DI 的中心点之一是启用 松散耦合 到 易失性依赖关系 。并非 class 所依赖的所有类型都是 volatile。有些是 稳定的 并且没有必要阻止在 class 中创建稳定的依赖项。两者的第一章 Dependency Injection in .NET (by Mark Seemann) and its successor Dependency Injection Principles, Practices, and Patterns (by Mark and I) have a detailed description of what Volatile Dependencies and Stable Dependencies 是什么以及它们有何不同。
您应该问的主要问题是 WebClientService
所依赖的任何类型是否为易失性依赖项。答案取决于你的特定上下文,你应该能够在(重新)阅读第 1 章后弄明白这一点。本章可以在线免费阅读。