2

我正在尝试学习依赖注入,但我还没有掌握许多微妙之处。为此,我开始阅读的其中一本书是Karl Seguin 的编程基础。有一个关于依赖注入的例子:

public class Car
{
    private int _id;

    public void Save()
    {
        if (!IsValid())
        {
            //todo: come up with a better exception
            throw new InvalidOperationException("The car must be in a valid state");
        }

        IDataAccess dataAccess = ObjectFactory.GetInstance<IDataAccess>();
        if (_id == 0)
        {
            _id = dataAccess.Save(this);
        }
        else
        {
            dataAccess.Update(this);
        }
    } 
}

然后他继续建议添加另一个间接级别,而不是ObjectFactory直接在方法中调用:

public static class DataFactory
{
    public static IDataAccess CreateInstance
    {
        get
        {
            return ObjectFactory.GetInstance<IDataAccess>();
        }
    }
}

但这不是“服务位置”吗?

4

3 回答 3

2

它是服务定位器。有几种使用依赖的方法:

  • 聚合(示例)

  • 作品

    • 构造函数中的 DI,强制(可以在上层使用 SL 注入)

    • 属性中的 DI,可选(可以在上层使用 SL 注入)

选择什么取决于许多因素,例如它是稳定依赖还是不稳定依赖,是否需要在测试中模拟它等等。Mark Seemann 有一本关于 DI 的好书,名为“.NET 中的依赖注入”。

于 2013-02-06T19:32:46.700 回答
1

是的,对我来说看起来像 SL。依赖注入传统上遵循两种模式之一;属性注入或构造函数注入。

依赖注入一开始感觉比服务位置更努力,但服务位置 (SL) 有许多负面影响。使用服务定位器太容易了,不能随心所欲地疯狂请求服务,到处都是。这很好,直到你去重构并意识到耦合“太高了”。

对于 DI,我更喜欢构造函数注入形式,因为它迫使我预先考虑谁需要什么。

总而言之,我目前的项目是作为一个使用服务定位器的绿地项目开始的,因为它给了我“不”考虑依赖关系并让应用程序形状发展的灵活性。最近我一直在重构以使用 DI,主要是为了了解什么依赖于什么以及为什么。

于 2013-02-06T19:23:20.140 回答
1

您的示例是 ServiceLocator。总有一个 ServiceLocator 某处。我想说关键是要理解为什么你会直接使用它,以及为什么理想情况下你可能不必这样做。

关键概念是依赖倒置原则。依赖注入和控制框架的反转是促进主体应用的工具。理想情况下,您希望您的对象构造函数参数是将在对象创建时解析的接口定义。

如果您使用的是现代工具,例如 asp.net MVC,那么您可以访问所谓的组合根,它是应用程序的入口点。在 MVC 中它是控制器。由于您可以访问组合根目录,因此您不需要使用 ServiceLocator,因为注入是由您注册和设置的 IOC 框架从顶部为您驱动的。基本上,您的控制器具有像 ISomeService 这样的构造函数参数,这些参数在 IOC 中注册并在创建控制器实例时自动注入。如果 ISomeService 有一些依赖关系,它们也将作为 ISomeUtility 在构造函数中,以此类推,因为您的对象越来越深。这是理想的,您永远不需要使用 ServiceLocator 来解析对象。

如果您使用的技术不允许您访问根目录,或者如果您想在没有 IOC 框架的应用程序中开始使用它并且您是第一次添加它,那么您可以发现你无法进入作文根目录。这可能是框架或代码质量的限制。在这些情况下,您必须使用 ServiceLocator 或自己直接创建对象。在这些情况下,使用 ServiceLocator 是可以的,并且比自己创建该对象更好。

于 2013-02-06T20:53:05.797 回答