[英]How does one use dependency injection outside of an MVC context?
Every example I see for dependency injection is paired with MVC for some reason as if nothing else exists outside of web projects. 出于某种原因,我看到的每个用于依赖项注入的示例都与MVC配对,就像在Web项目之外没有其他东西一样。 I take issue with this because there is a contradiction going on with MVC utilizing dependency injection but it delivers those dependencies through a Dependency Resolver which to me is just another name for a Service Locator.
我对此有疑问,因为使用依赖注入的MVC一直存在矛盾,但是它通过依赖关系解析器传递这些依赖关系 ,在我看来, 依赖关系解析器只是服务定位器的另一个名称。
With all that being said, how do you use DI with a simple console application? 综上所述,如何在简单的控制台应用程序中使用DI?
I see a lot of programmers making these mistakes and honestly I can't blame them for it. 我看到很多程序员犯了这些错误,老实说,我不能为此而责怪他们。 There isn't a clear solution outside of MVC which is clearly using the dreaded Service Locator.
MVC之外没有一个明确的解决方案,它显然使用了可怕的 Service Locator。
Something I don't feel good about doing is pass a dependency through a chain of objects to use it in a deeply nested piece of code. 我对此不满意的事情是通过一个对象链传递一个依赖关系,以在深层嵌套的代码段中使用它。 This just feels wrong.
这只是感觉不对。
This is a watered down example of something I am working on to demonstrate my concern. 这是我正在努力表达自己关心的事情的典型例子。 I don't like passing the SMTP client dependency through a class, just to give it to another class.
我不喜欢通过一个类传递SMTP客户端依赖项,而只是将其提供给另一个类。 You might be compelled to say "Inject the SmtpClient into ServiceClass then into EntryPoint".
您可能会被迫说“将SmtpClient注入ServiceClass,然后注入EntryPoint”。 In my example I cannot inject ServiceClass because it actually comes from a Factory pattern.
在我的示例中,我无法注入ServiceClass,因为它实际上来自于Factory模式。
public static void Main(string[] args)
{
var smtpClient = _container.GetDependency<ISmtpClient>();
//When I do this manually I feel like it defeats the purpose of DI
var ep = new EntryPoint(smtpClient);
ep.RunAProcess();
}
public class EntryPoint
{
private readonly ISmtpClient _smtpClient;
public EntryPoint(ISmtpClient smtpClient)
{
//EntryPoint doesn't use this dependency
_smtpClient = smtpClient;
}
public void RunAProcess()
{
/* More code here */
//ServiceClass actually comes from a Factory, but I didn't
//want to make this example too long
var svc = new ServiceClass(_smtpClient);
svc.Send();
}
}
public class ServiceClass
{
private readonly ISmtpClient _smtpClient;
public ServiceClass(ISmtpClient smtpClient)
{
//ServiceClass uses this dependency
_smtpClient = smtpClient;
}
public void Send()
{
using (var mail = CreateMailMessage(message))
{
_smtpClient.Send(mail);
}
}
}
This is the closest SO question I found in relation to my query: DbContext Dependency Injection outside of MVC project 这是与查询有关的最接近的SO问题: MVC项目外部的DbContext依赖注入
Outside of MVC you can use HostBuilder
see https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/generic-host?view=aspnetcore-2.2 在MVC之外,您可以使用
HostBuilder
参见https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/host/generic-host?view=aspnetcore-2.2
The general idea is that it works pretty much like the web version ( and will support console, windows services, and linux daemons etc ) 总体思路是,它的工作方式与网络版本非常相似(并且将支持控制台,Windows服务和linux守护程序等)
public static async Task Main(string[] args)
{
var host = new HostBuilder() .
.ConfigureServices(ConfigureServices)
.UseConsoleLifetime()
.Build();
await host.RunAsync();
}
private static void ConfigureServices(HostBuilderContext context, IServiceCollection services)
{
services
.AddTransient<IThing, Thingy>()
.AddTransient<Stuff>()
.AddHostedService<MyService>();
}
Your Hosted Service is like your main entry point and things from there will be injected.... 您的托管服务就像您的主要入口点一样,从那里开始会注入东西。
internal class MyService : IHostedService
{
public MyService(Stuff stuff) // injected stuff
{
}
public Task StartAsync(CancellationToken cancellationToken)
{
}
public Task StopAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
}
This is more a matter of misunderstanding the design principles. 这更多是对设计原理的误解。
Something I don't feel good about passing a dependency through a chain of objects to use it in a deeply nested piece of code.
我对通过一系列对象传递依赖项以在深层嵌套的代码中使用依赖项感到不满意。 This just feels wrong.
这只是感觉不对。
The core of your issue is about understanding how to apply a clean design which allows loose coupling and high cohesion. 您问题的核心是了解如何应用干净的设计,以实现松散的耦合和高内聚力。 Whether it is Asp.Net MVC or console application is an implementation detail.
无论是Asp.Net MVC还是控制台应用程序都是实现细节。
The watered down example in this case is not following a clean design as EntryPoint
is tightly coupling to ServiceClass
and also violates the Explicit Dependencies Principle . 在这种情况下,经过简化的示例并未遵循干净的设计,因为
EntryPoint
与ServiceClass
紧密耦合,并且还违反了“ 显式依赖原则” 。
EntryPoint
in this example is not being genuine about its dependencies. 在此示例中,
EntryPoint
不是关于其依赖关系的真实EntryPoint
。 If it does not use ISmtpClient
directly then it should not explicitly depend on it just to pass it on. 如果它不直接使用
ISmtpClient
,则不应明确地依赖它来传递它。
And if ServiceClass
is coming from a factory then the factory should be applied at the composition root and then explicitly injected into EntryPoint
如果
ServiceClass
来自工厂,则应将工厂应用于组合根,然后显式注入EntryPoint
Review the following refactoring to see what I am referring to 查看以下重构,以了解我指的是什么
public static void Main(string[] args) {
//ISmtpClient should be injected into ServiceClass
//when resolved by the container or factoty
IService service = _container.GetDependency<IService>();
var ep = new EntryPoint(service);
ep.RunAProcess();
}
public class EntryPoint {
private readonly IService service;
public EntryPoint(IService service) {
this.service = service;
}
public void RunAProcess() {
/* More code here */
service.Send(message);
}
}
public class ServiceClass : IService {
private readonly ISmtpClient _smtpClient;
public ServiceClass(ISmtpClient smtpClient) {
//ServiceClass uses this dependency
_smtpClient = smtpClient;
}
public void Send(Message message) {
using (var mail = CreateMailMessage(message)) {
_smtpClient.Send(mail);
}
}
}
So even if you apply pure dependency injection at the composition root, only the actual dependencies are injected into the target dependent. 因此,即使您在组合根目录应用纯依赖项注入 ,也只会将实际依赖项注入到目标依赖项中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.