我想了解如何实现依赖注入,但我有一些问题:
我可以使用抽象类吗?我读了一些关于 DI 的文章,如果我理解得很好,他们说你必须使用接口而不是抽象类 - 如何避免在不同的类中使用重复的代码?
如果我在一个类中有很多依赖项,我是否必须在构造函数中注入所有这些依赖项?如果我没有在所有方法中都使用它们怎么办?
我可以实例化对象吗?如果我不实例化对象,我如何调用类的构造函数?
答案 0 :(得分:4)
我可以使用抽象类吗?
是的。然而,在实践中,使用接口可能有一些优势。例如,有时在测试时模拟接口比抽象类更容易。我还会问你为什么觉得需要使用抽象类而不是接口,但这引出了下一点......
<块引用>如何避免在不同的类中使用重复的代码?
一般来说,您应该 favor composition over inheritence 以实现代码重用。
<块引用>如果我在一个类中有很多依赖项,我是否必须将它们全部注入到构造函数中?
不,还有其他方法可以注入依赖项,例如方法。但我会说构造函数注入是“经典”的 DI 模式,它有一些优点。例如,如果您在构造函数中注入所有依赖项,那么您无需担心在设置所需的依赖项之前有人在您的类上调用方法。
<块引用>如果我不在所有方法中都使用它们怎么办?
这在小范围内是可以的。但是,如果您有很多依赖项或很多方法,这可能表明您的类做得太多了。如果您有不同的方法/依赖项组(例如,如果方法 A、B、C 使用依赖项 1、2,而方法 D、E、F 使用依赖项 3、4),则尤其如此。见Single Responsibility Principle。
<块引用>我可以实例化对象吗?如果我不实例化对象,我如何调用类的构造函数?
考虑不同类型的类很重要。您不需要将 DI 用于简单地保存数据的简单 POCO 类——您可以根据需要随意new
。但是,DI 对于执行某些业务逻辑或与某些外部系统(如数据库)交互的服务类型类非常重要。在这种情况下,您不应该使用 new
在您的类中实例化它们。
当然,您必须在某个时候实例化这些对象。但是 DI 的重点是依赖于 X 的类不应该也实例化 X。依赖注入框架通常有一个“组合根”,所有依赖都在其中连接起来。您会在那里看到正在创建的新实例。
答案 1 :(得分:0)
简答:
inject
。 (构造函数在很多方面只是一种)。decorator
来保存有关依赖项的描述,然后您使用它来创建实例。答案 2 :(得分:0)
1- 我可以使用抽象类吗?我读了一些关于 DI 的文章,如果我理解得很好,他们说你必须使用接口而不是抽象类,但是我如何避免在不同的类中使用重复的代码?
我认为你在谈论两件不同的事情。
A.您可以使用抽象类,而不必使用接口。这是一个例子。
internal abstract class BaseService
{
public abstract string GetString();
}
internal class ServiceC : BaseService
{
public override string GetString() => "ServiceB";
}
internal class ServiceD
{
public ServiceD(BaseService baseService) { BaseService = baseService; }
public BaseService BaseService { get; }
}
static void Main(string[] args)
{
// ServiceCollection is package Microsoft.Extensions.DependencyInjection
var serviceProvider = new ServiceCollection()
.AddSingleton<BaseService, ServiceC>()
.AddSingleton<ServiceD>()
.BuildServiceProvider();
var serviceC = serviceProvider.GetService<BaseService>();
var serviceD = serviceProvider.GetService<ServiceD>();
//serviceD.BaseService is ServiceC
B.即使您使用接口,您仍然可以使用抽象类,用于非 DI 部分。
请考虑以下示例。
internal abstract class BaseService { protected string GetCommon() => "Common functionality"; }
internal interface IServiceA { string GetA(); }
internal interface IServiceB { string GetB(); }
internal class ServiceA : BaseService, IServiceA
{
public string GetA() => "A + " + GetCommon();
}
internal class ServiceB : BaseService, IServiceB
{
public string GetB() => "B + " + GetCommon();
}
static void Main(string[] args)
{
// ServiceCollection is package Microsoft.Extensions.DependencyInjection
var serviceProvider = new ServiceCollection()
.AddSingleton<IServiceA, ServiceA>()
.AddSingleton<IServiceB, ServiceB>()
.BuildServiceProvider();
var serviceA = serviceProvider.GetService<IServiceA>();
Console.WriteLine(serviceA.GetA()); // "A + Common functionality"
Console.WriteLine(serviceProvider.GetService<IServiceB>().GetB()); // B + Common functionality
}
您可以在方法中使用额外的依赖项。
internal class ServiceE
{
private readonly IServiceA a;
public ServiceE(IServiceA a)
{
this.a = a;
}
public string AandB(IServiceB b) => a.GetA() + b.GetB();
}