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

Dependancy issue with static utility classes with repository (.NET MVC project)

我有一个带有标准IOC设置的MVC项目,它使用结构映射将存储库注入控制器构造函数。

我还决定要有一个静态的"实用程序"类,在这个类中,我可以有可以由不同的控制器调用的公共方法。例如,我有:

1
2
3
4
5
6
public static IEnumerable<CountryCode> GetCountryList()
{
    ICountryCodeRepository repo = ObjectFactory.GetInstance<ICountryCodeRepository>();
    IEnumerable<CountryCode> countries = repo.GetAll();
    return countries;
}

正如您所看到的,它直接从ObjutFr工厂创建一个RePO对象。现在的问题是,当我想对我的控制器进行单元测试时,我可以模拟控制器的RePOS,但不是公用事业类中的RePOS(控制器最终调用)。我确信还有其他原因导致我的实用程序类是错误的,但这就是我目前看到的。我也读过一些东西,说我的设计很差,只是不知道如何修复。

我想让getCountryList()函数接受repo对象

1
GetCountryList(ICountryCodeRepository _repo)

调用控制器会将其传入,但这不只是创建另一个依赖关系问题吗,因为所有控制器都必须知道实用程序功能需要什么?

或者可以使用structuremap以某种方式注入这些实用方法吗?


至少你知道你所做的是糟糕的设计是可以的。很好,阅读这篇文章的人也会知道这一点,并且避免犯和你一样的错误。

但现在,您可以在静态类中使用一个提供程序:

1
2
3
4
5
6
7
8
9
10
public static class Foo
{
    public static Func<ICountryCodeRepository> CountryRepoProvider =
        () => ObjectFactory.GetInstance<ICountryCodeRepository>();

    public static IEnumerable<CountryCode> GetCountryList()
    {
        return CountryRepoProvider().GetAll();
    }
}

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

1
Foo.CountryRepoProvider = () => mocha;

或者,如果您使用的是ASP.NET MVC 3,而DI框架使用的是依赖关系解析程序,则可以通过至少使其不受DI框架影响来改进此代码:

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

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

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

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