我对一些建筑方法很感兴趣。我喜欢DI和IOC,但我不理解costructor注入;为什么这么复杂。我编写了下面的代码,它使用了构造函数注入:
namespace DependencyInjection
{
class Program
{
static void Main(string[] args)
{
ConstructorInjectionClass myCtx = new ConstructorInjectionClass(new PdfFormat());
myCtx.Print();
Console.Read();
}
}
public interface IFormat
{
void Print();
}
public class PdfFormat : IFormat
{
public void Print()
{
Console.WriteLine("Pdf Format Print is completed...");
}
}
// Constructor Injection
public class ConstructorInjectionClass
{
private IFormat _format;
public ConstructorInjectionClass(IFormat format)
{
_format = format;
}
public void Print()
{
_format.Print();
}
}
我在下面写了一些代码。我认为这很简单。
public interface IFormat
{
void Print();
}
public class PdfFormat : IFormat
{
public void Print()
{
Console.WriteLine("Pdf Format Print is completed...");
}
}
public interface ISave
{
void Add();
}
public class Sql: ISave
{
public void Add()
{
Console.WriteLine("Adding to SQL is completed...");
}
}
// Constructor Injection
public class ConstructorInjectionClass
{
public ConstructorInjectionClass(IFormat format)
{
format.Print();
}
public ConstructorInjectionClass(ISave saver)
{
saver.Add();
}
为什么要使用构造函数注入?这两种方法的优缺点是什么?
答案 0 :(得分:4)
第一个例子是构造函数注入。你正在注册班级负责打印到课堂上。
在第二个示例中,您将使用2个参数之一创建一个新类,并使用构造函数中的参数。这有几个原因:
ISave
和IPrint
实现上的方法。毕竟它必须让它们能够将它们传递给方法。如果你的对象在内部保存它们,那么它们可以在构造对象时提供(比如在你的组合根目录中),并且在你的对象上调用Print
的客户端代码不需要知道关于{的事实。存在{1}}和ISave
个实现,构造函数注入是关于你的类要求它在它的构造函数中具有的依赖关系,所以很清楚依赖是什么。通过要求依赖而不是创建它们,测试类变得更简单,因为您可以为测试目的注入模拟依赖项。
第一个选项很好,如果你想添加保存,那么你应该为构造函数添加一个额外的参数来获取IPrint
接口以及ISave
接口并有一个方法{ {1}}将委托给IPrint
implmentation。
通过注入依赖项并通过编程到接口,可以更轻松地在以后更改功能。例如,您可以轻松地对文件进行处理(通过更改传入的Save
接口或更改它以保存到xml文件或Web服务,方法是更改传递它的ISave
实现这使你的课程松散地与保存和打印实现相结合
我会阅读this关于DI / IOC的更多指导的优秀答案
答案 1 :(得分:4)
好吧,与任何模式一样,构造函数注入应该在当且仅当使用它时才使用。你的示例代码有点奇怪......
Print
的方法,它依赖于另一个类来进行打印。它不需要实例化此依赖项,而是要求在其构造函数中提供依赖项。这是Dependency Inversion Principle的典型示例。基本上:“要求,不要实例化。”答案 2 :(得分:1)
假设您想要注入依赖项...您可以通过构造函数注入或通过属性设置器来执行此操作。我认为构造函数注入的一个优点是IOC使用这种策略。所以,如果你不确定你想去IOC,但你想做DI,那么应该使用构造函数注入来转换到IOC后...更容易......如果你应该改变主意......