带有存储库的静态实用程序类的依赖性问题(.NET MVC 项目)



我有一个带有标准 IoC 设置的 MVC 项目,该项目使用 StructureMap 将存储库注入控制器构造函数。

我还决定想要一个静态的"实用程序"类,在那里我可以拥有可由不同控制器调用的通用方法。例如,我有:

public static IEnumerable<CountryCode> GetCountryList()
{
    ICountryCodeRepository repo = ObjectFactory.GetInstance<ICountryCodeRepository>();
    IEnumerable<CountryCode> countries = repo.GetAll();
    return countries;
}

如您所见,这直接从 ObjectFactory 创建一个存储库对象。现在的问题是,当我想对我的控制器进行单元测试时,我可以模拟控制器的存储库,但不能模拟实用程序类中的存储库(控制器最终调用)我确信还有其他原因导致我的实用程序类是错误的,但这就是我目前看到的。我也读过一些东西,说我拥有的是糟糕的设计,我只是不知道如何解决它。

我正在考虑让 GetCountryList() 函数来接受存储库对象

GetCountryList(ICountryCodeRepository _repo)

调用控制器会将其传入,但这不就是产生另一个依赖关系问题,因为所有控制器都必须知道实用程序函数需要什么?

或者是否可以以某种方式使用StructureMap来注入这些实用程序方法?

至少你知道你正在做的是糟糕的设计是可以的。这很好,阅读这篇文章的人也会知道这一点,并避免犯与您相同的错误。

但是现在说到点子上,你可以在静态类中使用一个提供程序:

public static class Foo
{
    public static Func<ICountryCodeRepository> CountryRepoProvider = 
        () => ObjectFactory.GetInstance<ICountryCodeRepository>();
    public static IEnumerable<CountryCode> GetCountryList()
    {
        return CountryRepoProvider().GetAll();
    }
}

现在在你的单元测试中,你可以模拟它:

Foo.CountryRepoProvider = () => mocha; 

或者,如果您使用的是 MVC 3 ASP.NET 并且您的 DI 框架使用依赖解析器,您可以通过至少使其与 DI 框架无关来改进此代码:

public static IEnumerable<CountryCode> GetCountryList()
{
    var repo = DependencyResolver.Current.GetService<ICountryCodeRepository>();
    return repo.GetAll();
}

现在在你的单元测试中,你当然可以编写一个自定义的依赖关系解析器,它将吐出你的服务的模拟实例。

现在,当你看到这段代码时,你可能会对自己说:我在做什么我正在编写一个静态类,其中包含一个委托给我从 DI 获取的存储库的行方法。当我可以从我的 DI 框架中受益,直接将这个存储库的实例注入到我需要的地方,然后简单地调用我需要的方法,这有什么意义?我在那些单衬静态方法中进行的单元测试是什么?我为什么要浪费时间

当然,如果你有更复杂的逻辑要处理,你只需编写一个服务层,它将必要的存储库作为构造函数依赖项,并对它们执行复杂的业务操作。然后,您只需将 DI 框架配置为在控制器中或任何需要的地方注入准备使用的服务实例。看?不需要任何静态类。弱耦合和单元测试友好代码。

最新更新