【问题标题】:Wrapping an API to support dependency injection包装 API 以支持依赖注入
【发布时间】:2011-03-16 22:51:07
【问题描述】:

我正在与只有静态函数的 API 交互,无法打开和更改。

    public class WindowsNativeGraphAPI
    {
        public static IEnumerable<IGraphData> GetGraphData();
        public static bool DeleteGraphData(IGraphData data);
    }

我希望能够将 API 传递到函数或构造函数中并遵守依赖注入(以防我们稍后更换 API)。

public void GatherGraphData(IGraphAPI api)
{...}

为了允许这个 API 作为参数传入,我至少需要抽象以使用接口传递给函数。

    public interface IGraphAPI
    {
        IEnumerable<IGraphData> GetGraphData();
        bool DeleteGraphData(IGraphData data);
    }

但是,我需要在另一个类中实现接口,因为我无法更改原始 API。此类将是 API 的轻量级包装器,它只调用 API 上的相应函数并返回相同的结果。

    public class WindowsGraphAPI : IGraphAPI
    {
        public IEnumerable<IGraphData> GetGraphData()
        {
            return WindowsNativeGraphAPI.GetGraphData();
        }

        public bool DeleteGraphData(IGraphData data)
        {
            return WindowsNativeGraphAPI.DeleteGraphData(data)
        }
    }

我不喜欢创建另一个类来包装 API 的想法。我知道这个包装器会非常轻量级并且只会返回 API 的结果,但是我该如何测试包装器呢?包装器可能还应该包含一些异常处理来处理 API 中的错误。如果我们要更改为遇到同样问题的另一个 API,我们将不得不再次创建这些额外的类和接口。

理想情况下,最终结果将是一个可模拟的 API,可以在为使用它的新组件编写单元测试时使用。

这是正确的方法吗?可以换一种方式吗?

谢谢

【问题讨论】:

    标签: c# .net dependency-injection wrapper static-methods


    【解决方案1】:

    是的,这是正确的方法。新的 API 接口和代理类封装了使用哪个底层库的决定 - 单一职责。

    【讨论】:

    • +1 ASP.NET MVC 广泛地做到了这一点,因此它提供了一组示例来演示这种方法。
    【解决方案2】:

    是的,这是正确的方法。我不会在您的包装器中放置异常处理,您所做的只是创建一个调用静态方法的类,以便您可以使用 DI。您希望包装器在与具有静态方法的 API 类相同的情况下引发相同的异常。这样,您可以在方法中使用与使用静态方法调用类时相同的异常处理。然后,您可以在模拟 api 类中在相同情况下抛出相同的异常并测试异常处理。

    【讨论】:

    • 我不同意这些关于例外的说法。异常是 API 功能契约的一部分。如果适配 API 抛出的异常类型是在包含适配 API 本身的包中定义的,那么允许这些异常通过将使实现细节通过抽象泄漏。最好将它们包装在与接口一起定义的异常中。
    • 从学术的角度来看这听起来很棒,但在实践中,您要么在抽象异常中得到足够的细节,从而使实时代码中的调试问题变得很痛苦,要么您必须做一个创建复杂异常处理以提供足够的细节以供以后调试的工作量,只是为了说明您可能在某些时候完全更改实现而不是仅仅模拟 Windows API 以进行单元测试。
    • 我并不是说包装器必须包装适配的 API 抛出的异常。我要说的是,客户端不得依赖于适配的 API 定义的异常类型,因为这会造成紧密耦合。 DI 不仅仅是可测试性。
    • 我明白你的意思,但你必须非常小心,确保所有相关信息都被正确记录和处理。我刚刚花了太多时间希望来自某些基本 API 的异常能够以纯正的方式进入日志文件,因为没有它们,我几乎不可能有时间试图找出为什么某些代码不起作用。
    • 拥有一个嵌套异常成员和体面的日志记录将其从学术性转变为非常实用的可维护性。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-01-04
    • 2017-12-09
    • 2020-12-20
    • 1970-01-01
    • 1970-01-01
    • 2017-10-22
    • 1970-01-01
    相关资源
    最近更新 更多