0

我正在尝试在应用程序中使用依赖注入技术,但如果此上下文需要 DI,我会感到困惑..

考虑一个接口:

public class ICardsHub {
    public T GetPlayersList<T>();
}

及其实施:

public class GenericHub : ICardsHub {

    LANPlayers LANPlayers;
    WaNPlayers WANPlayers;
    bool AlgorithmsUseTildainLambdas=false;

    public GenericHub(LANPlayers _LANPlayers, WaNPlayers _WANPlayers, 
                           bool algorithmsUseTildainLambdas=false) {
        LANPlayers = _LANPlayers;
        WANPlayers = _WANPlayers;
        AlgorithmsUseTildainLambdas = algorithmsUseTildainLambdas;
    }

    public T GetPlayersList<T>() {
        ....
    }

}

并且驱动程序类应该执行以下操作:

ICardsHub _ifCards = new GenericHub(_LANPlayers, _WANPlayers);
listOfPlayers = _ifCards.GetPlayersList<List<string>>();

现在,我们还有两个实现ICardsHubRedHub并且BlackHub稍后在驱动程序类中实例化。

问题

  1. Unity IoC/DI如何使这种情况受益?
  2. 如果striping out method parameters from the interface and injecting them to overload constructor解决了问题,那么 DI 容器使用的合适场景是什么?
4

3 回答 3

2

DI 使代码易于维护并易于切换到新的实现。我同意重载的构造函数可以达到目的,但是如果您有很多依赖项,我们仍然必须手动确保代码更改以有效地到达每个地方并手动更改它,有时您可能会错过其中的一些。有一个中心位置将有助于易于维护。这就是为什么不建议将 DI 用于较小的项目但良好的大型项目的原因。我认为 DI 的目的不是解决 TDD,而是更好的可维护性和轻松切换到新的类实现。例如,今天您使用 SQL SERVER 作为数据库,明天您更改为 NOSQL。类名中的一处更改将确保在所有地方与 DB 交互的所有代码都可以正常工作。TDD 就是其中的一个例子

于 2013-03-30T02:14:09.320 回答
1

DI 的主要动机是可测试性,恕我直言。所以,如果你在测试范式之外看,可能会有一些混乱。

在您描述的示例中,我看到 ICardsHub 为 GenericHub、RedHub 和 BlackHub 的实现定义了一个合同。

现在,这些实现中的每一个都将具有一些使其不同的逻辑,因此需要存在不同的类。

为了测试这些类(它们的职责是独一无二的),在这些类可以执行它们的工作之前需要执行一些步骤,并且可能会发布这些步骤。

此类测试的范围是确保在给定“前”步骤没有错误的情况下,此类执行的操作将为“后”步骤使用无错误输出。

考虑到这一点,依赖注入允许我们

  1. 轻松假设前提条件(即注入模拟对象,并设置假设)
  2. 执行一个动作(这个类的职责)
  3. 验证输出。

顺便说一句,您的实现应该注入接口而不是具体类型。就像是 -

ILANPlayers LANPlayers;
IWaNPlayers WANPlayers;
bool AlgorithmsUseTildainLambdas=false;

public GenericHub(ILANPlayers _LANPlayers, IWaNPlayers _WANPlayers, 
                       bool algorithmsUseTildainLambdas=false) {
    LANPlayers = _LANPlayers;
    WANPlayers = _WANPlayers;
    AlgorithmsUseTildainLambdas = algorithmsUseTildainLambdas;
} 

所以在测试中你可以模拟这些类型的模拟实现ILanPlayersIWanPlayers

于 2013-03-30T02:13:12.057 回答
0

一般来说,您只使用 DI 来帮助您执行单元测试。您应该针对接口进行编码,因此,通过使用 DI,您可以轻松地模拟您的组件。

在您的场景中,您将有一些使用 ICardHub 接口实现的客户端类,现在的问题是,这些实现中的任何一个是否会执行数据库操作或任何其他外部使用,如果不是,您很可能最好不使用 DI。

如果您仍想使用 DI,请改用 AutoFac,IMO 很容易使用。

如果您有一些您认为可以创建“库”的代码,那么这是 DI 的一个很好的候选者。您必须将这些组件视为提供者,而 DI 通常并不是什么新鲜事。DI 只是消除了您的应用程序创建它需要的提供程序实例的责任,它是 DI 容器执行此操作,并且您的应用程序仅使用接口。

这是一个例子:

  • 无 DI

    IDatabase database = new SqlServer();
    
  • 带 DI

    IDatabase database = DIContainer.Get<IDatabase>();
    

如您所见,即使您的应用程序将使用 SqlServer 数据库,它对此一无所知。是的,您必须在 DI 容器中注册该类型,但您只需注册一次,因此如果您以后决定更改为其他实现,这很容易。

于 2013-03-30T02:12:43.100 回答