解释 C# 中的依赖注入
依赖项是另一个对象所依赖的对象。依赖注入(或倒置)基本上是提供对象需要的对象,而不是让它自己构造对象。这是一种使测试更容易的有用技术,因为它允许您模拟依赖项。
例如,如果类A调用类B上的方法,而后者又调用类C上的方法,则意味着A依赖于B,B依赖于C。使用依赖注入,我们可以将类C的实例传递给类B,并将B的实例传递给类A,而不是让这些类来构造B和C的实例。
在下面的示例中,Runner类依赖于Logger类。请注意,在Runner类中,在构造函数中创建了Logger的一个实例。这段代码有几个问题。
这将记录器类与Runner联系起来,我们不能用其他类替换它,而不修改Runner。
如果Logger有任何依赖项,那么Worker必须在实例化Logger之前配置它们。
测试更难。如果Logger是资源密集型类,例如访问网络或文件系统,它会减慢测试速度。我们不能轻易更换它。
using System; class Program{ static void Main(string[] args){ var runner = new Runner(); runner.Run(); } } class Runner{ private Logger _logger; public Runner(){ _logger = new Logger(); } public void Run(){ //做一些工作 _logger.Log("Message to be logged"); } } class Logger{ public void Log(string message){ Console.WriteLine(message); } }
使用依赖注入,我们修改Runner的构造函数以接受一个接口ILogger,而不是一个具体的对象。我们更改Logger类以实现ILogger。这允许我们将Logger类的实例传递给Runner的构造函数。这样做的好处是,在测试期间,我们可以创建一个实现ILogger的TestLogger类并将其传递给Runner的构造函数。
示例
using System; class Program{ static void Main(string[] args){ var logger = new Logger(); var runner = new Runner(logger); runner.Run(); } } class Runner{ private ILogger _logger; public Runner(ILogger logger){ _logger = logger; } public void Run(){ //做一些工作 _logger.Log("Message to be logged"); } } interface ILogger{ void Log(string message); } class Logger : ILogger{ public void Log(string message){ Console.WriteLine(message); } }输出结果
Message to be logged