【问题标题】:Dependency Injection: I don't get where to start!依赖注入:我不知道从哪里开始!
【发布时间】:2011-01-03 11:44:30
【问题描述】:

我有几篇关于依赖注入的文章,我可以看到它的好处,尤其是在单元测试方面。这些单元可以松散耦合,并且可以模拟依赖关系。

问题是 - 我只是不知道从哪里开始。

考虑一下我拥有的代码(为了这篇文章的目的而进行了很多编辑)下面的这个 sn-p。我正在从主窗体实例化一个 Plc 对象,并通过 Connect 方法传入通信模式。

目前的形式很难测试,因为我无法将 Plc 与 CommsChannel 隔离开来对其进行单元测试。 (可以吗?)

该类依赖于使用 CommsChannel 对象,但我只传递了一种用于在 Plc 本身内创建此通道的模式。要使用依赖注入,我真的应该将已经创建的 CommsChannel(可能通过“ICommsChannel”接口)传递给 Connect 方法,或者可能通过 Plc 构造函数。对吗?

但这意味着首先在我的主窗体中创建 CommsChannel,这似乎也不对,因为感觉一切都会回到主窗体的基础层,一切都从这里开始。不知何故,我感觉我错过了拼图中的关键部分。

你从哪里开始?您必须在 somewhere 创建某个东西的实例,但我很难理解它应该在哪里。

public class Plc()
{
    public bool Connect(CommsMode commsMode)
    {
        bool success = false;

        // Create new comms channel.
        this._commsChannel = this.GetCommsChannel(commsMode);

        // Attempt connection
        success = this._commsChannel.Connect();  

        return this._connected;
    }

    private CommsChannel GetCommsChannel(CommsMode mode)
    {
        CommsChannel channel;

        switch (mode)
        {
            case CommsMode.RS232:
                channel = new SerialCommsChannel(
                    SerialCommsSettings.Default.ComPort,
                    SerialCommsSettings.Default.BaudRate,
                    SerialCommsSettings.Default.DataBits,
                    SerialCommsSettings.Default.Parity,
                    SerialCommsSettings.Default.StopBits);
                break;

            case CommsMode.Tcp:
                channel = new TcpCommsChannel(
                    TCPCommsSettings.Default.IP_Address,
                    TCPCommsSettings.Default.Port);
                break;

            default:
                // Throw unknown comms channel exception.
        }

        return channel;
    }
}

【问题讨论】:

标签: c# winforms design-patterns dependency-injection


【解决方案1】:

很难回答如此广泛的问题,但您关于在哪里/谁创建连接对象的具体问题更简单。

您可以传入一个工厂对象,该对象知道如何创建连接对象以及或代替模式。这样,如果您想创建不同的(例如模拟)连接,您只需传入一个不同的工厂对象,该对象在被要求创建连接时创建不同的连接实现。

这有帮助吗,还是我错过了真正的问题?

【讨论】:

  • 谢谢,这确实有帮助。好的,所以一个 CommsChannelFactory ......你的意思是有一个工厂使用,比如说,一个 ICommsChannelFactory 接口,然后在单元测试时用这个接口创建一个 MockCommsChannelFactory,然后返回一个虚拟的 ICommsChannel 对象? (我在正确的路线上吗?!)
  • 这听起来对我来说是正确的。这一切都归结为对象/实现的可插拔性,但要尽量保持平衡,否则接口和注入将呈指数级增长,我发现这会导致系统难以理解。
  • '很难理解'我不需要 :) 这个例子似乎是一个自然的地方,可以让接口分离关注点并使测试更容易,但我同意你的观点。
  • 我们正在讨论的工厂示例是接口的理想场所。问题是人们过度使用它而没有真正的价值,最终你会得到大量的小类,这会使系统难以理解,除非你完全理解设计师所拥有的心智模型。所以我的建议是当你意识到你应该有更多的注入而不是不断地把它分散到任何地方。
  • 我决定重构一些东西,以便将 ICommsChannel 实例传递给 Plc,这些实例是从一个单独的工厂生产的。这至少可以让我用一些模拟 ICommsChannels 对 Plc 进行单元测试。我会接受你的回答,因为它让我思考这些问题,谢谢。
【解决方案2】:

我会做什么。

在应用 S.O.L.I.D 原则时,您迟早会遇到依赖注入,因此与其直接投入行动,不如花点时间阅读这份出色的 pdf。

http://www.lostechies.com/blogs/chad_myers/archive/2008/03/07/pablo-s-topic-of-the-month-march-solid-principles.aspx

然后结帐。

http://structuremap.net/structuremap/

例如。

这是我一生中最好的一次骑行,希望这对你来说也是一次同样激动人心的体验。

【讨论】:

    猜你喜欢
    • 2016-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-12
    • 2011-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多