Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/304.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 通过构造函数在IoC中实施依赖关系?_C#_Interface_Dependency Injection_Inversion Of Control_Abstract Class - Fatal编程技术网

C# 通过构造函数在IoC中实施依赖关系?

C# 通过构造函数在IoC中实施依赖关系?,c#,interface,dependency-injection,inversion-of-control,abstract-class,C#,Interface,Dependency Injection,Inversion Of Control,Abstract Class,我试图接受使用IoC/依赖注入,同时编程到契约而不是特定类。我面临的困境是: 为IoC编写接口程序:我开始时IoC非常依赖接口。从Spring的示例项目来看,接口是与IoC签订合同进行编程时的必经之路 (…虽然抽象类通常更受欢迎:) 通过构造函数明确类依赖关系 我的直觉是,将依赖项传递给类的构造函数是一种很好的编程实践。事实上,这就是依赖注入 。。。除非您不能在接口/抽象类中强制构造函数签名:接口或抽象类都不允许定义构造函数签名。 另请参见不要在抽象类型中定义公共或受保护的内部构造函数。。。只有

我试图接受使用IoC/依赖注入,同时编程到契约而不是特定类。我面临的困境是:

  • 为IoC编写接口程序:我开始时IoC非常依赖接口。从Spring的示例项目来看,接口是与IoC签订合同进行编程时的必经之路

  • …虽然抽象类通常更受欢迎:)

  • 通过构造函数明确类依赖关系 我的直觉是,将依赖项传递给类的构造函数是一种很好的编程实践。事实上,这就是依赖注入

  • 。。。除非您不能在接口/抽象类中强制构造函数签名:接口或抽象类都不允许定义构造函数签名。 另请参见不要在抽象类型中定义公共或受保护的内部构造函数。。。只有当用户需要创建该类型的实例时,构造函数才应该是公共的

  • 此问题与前面的stackoverflow问题相关:

    但我的问题是:

    由于您无法在C#接口/抽象类中定义构造函数,如上所述,在实际层面上:

    你如何将这与合理的实践相协调

    编辑:谢谢你的回答。我希望能对这种情况下我应该做些什么有所了解。只是不使用构造函数参数?使用某种类型的Init()方法来获取依赖项?
    Edit2:谢谢你的回答,非常有帮助。

    你的IoC容器必须从一个具体类型构造一个对象,即使你传递的是一个接口。构造函数不是行为或状态契约,因此它不属于接口或抽象类的公共成员


    构造函数是一种实现细节,因此不需要将其定义与具体类分开。

    不能在接口中定义构造函数签名。无论如何,这是没有意义的,因为接口不应该强制执行实现的构造方式

    但是抽象类确实可以有构造函数。它们必须得到保护,因为公共构造函数也没有意义。它们只能由具体的子类调用

    IoC原则规定,您不应该让类A了解并实例化类B,而应该将对IB的引用传递给A的构造函数。这样,A就不需要了解类B,因此您可以轻松地用IB的其他实现替换类B


    因为您正在传入一个已经实例化的类B对象,所以IB接口不需要有构造函数签名

    我一直认为用一个(虚构的)例子来解释这一点更容易

    假设您有一个ICustomerRepository接口、一个IShoppingCartRepository接口和一个ICheckout接口。您有这些接口的具体实现—CustomerRepository、ShoppingCartRepository和CheckoutService

    您的CheckoutService具体类有一个构造函数,它接受ICCustomerRepository和IShoppingCartRepository,例如

    public CheckoutService(ICustomerRepository customerRepository, IShoppingCartRepository shoppingCartRepository)
    {
      // Set fields for use in some methods later...
      _customerRepository = customerRepository;
      _shoppingCartRepository = shoppingCartRepository;
    }
    
    然后,当您希望ICheckoutService实现执行一些工作时,您可以告诉IoC容器它应该为每个接口类型使用哪个具体类,并要求它构建ICheckoutService。IoC容器将为您构建类,将正确的具体类注入CheckoutService的构造函数中。它还将构建从类继承权一直到类继承权的依赖关系,因此,例如,如果ShoppingCartRepository在构造函数中采用IDatabaseSession接口,那么只要您告诉IoC容器要将哪个具体类用于IDatabaseService,IoC容器也将注入该依赖关系

    以下是一些在配置(例如)为IoC容器时可能使用的代码(此代码通常在应用程序启动时调用):

    公共类权限:注册表
    {
    公共评估学()
    {
    ForRequestedType()。默认的ConcreteType();
    ForRequestedType()。默认的ConcreteType();
    //等等。。。
    }
    }
    
    然后,要构建ICheckoutService实例并准备就绪,并将所有依赖项传递到构造函数中,您可以使用以下方法:

    var checkoutService = ObjectFactory.GetInstance<ICheckoutService>();
    
    var checkoutService=ObjectFactory.GetInstance();
    
    我希望这是有道理的

    啊哈!因此,我可以继续使用构造函数参数来明确依赖关系,同时对契约进行编程。但是让IoC容器担心如何正确注入这些依赖项。谢谢,这完全澄清了这一点。
    var checkoutService = ObjectFactory.GetInstance<ICheckoutService>();