使用具有运行时参数的构造函数的Unity依赖注入

时间:2014-12-09 15:39:58

标签: c# asp.net-mvc dependency-injection dependencies unity-container

我掌握了依赖注入的基础知识,但我正在努力将其整合到一个使用Unity的MVC API C#应用程序中。我遇到的问题是我将拥有一个具有方法的控制器,并且在该方法中它将说两个对象。其中一个对象将依赖于数据访问层,而另一个对象则不依赖于数据访问层。我不确定如何设置它。

假设我有一个控制器,它使用以下方法从搜索对象中获取用户。它还使用SearchParameters对象来执行搜索。如果您搜索没有名称,则会获得所有结果,或者如果您输入名称,则会获得具有该名称的任何用户。

public Users[] GetUsers(string name) {
    Company.SearchParameters searchParams = new Company.SearchParameters(name);
    Company.UserSearchService searchService = new Company.UserSearchService(searchParams);

    return searchService.Search();
}

这当然是一个超级简化版本,但在这种情况下,Search方法中的UserSearchService正在进行显式数据库调用。所以我知道这是一种依赖,我必须给予它。 SearchParameters实际上只是一个保存数据的类。

以下是我不确定下一步该做什么的地方。 Controller本身并没有依赖关系,但是由于UserSearchService我不确定如何使用unity我正确地设置了它并考虑了构造函数的运行时值。我也不确定SearchParameters是否应被视为依赖关系。

此外,SearchParameters和UserSearchService没有任何类型的支持接口,如果这很重要,并且此控制器上还有其他方法与其他类似的数据访问层相关性需求,例如Company.UserAccount。< / p>

2 个答案:

答案 0 :(得分:0)

我在这里看到两个任务。第一个是重构,其中静态依赖项必须用接口替换。第二个任务是在IoC容器中注册你的东西。

对于第一项任务,您至少需要将DatabaseUserSearchService的所有引用替换为IDatabase接口(以便它也可以被模拟)并允许它传递给构造函数(构造函数注入)。为了能够为服务提供IDatabase的实例,您必须为控制器创建相同的依赖项(再次构造函数注入)。然后注册IDatabase实施,如this post

所示

<强>更新

我同意必须从控制器中删除依赖项。正如@Topojijo建议UserSearchService的工厂可以在这种情况下使用。猜猜你有几个需要为每个工厂建造一个工厂,如果他们的数量很大,可能会产生开销。在这种情况下,最好从Unity容器中resolve the service directly并将searchParams移动到Search方法:

public Users[] GetUsers(string name) {
    Company.SearchParameters searchParams = new Company.SearchParameters(name);
    Company.UserSearchService searchService = container.Resolve<Company.UserSearchService>();

    return searchService.Search(searchParams);
}

答案 1 :(得分:0)

搜索参数不应该是构造函数的一部分;它应该是“搜索”方法的一部分。甚至不应该在UserSearchService类(Encapsulation)之外知道SearchParameter对象。应该像neleus建议的那样进行一些重构。至少,为了让事情顺利进行,它应该被重构为类似的东西:

public Users[] GetUsers(string name) {
    // Or however you end up with your UserSearchService object.  
    // Ideally as an interface and an injected dependency...
    Company.UserSearchService searchService = new Company.UserSearchService();

    return searchService.Search(name);
}

<强> Company.UserSearchService:

public Users[] Search(string name) {
    // A factory would be a better option.  This should also be an interface.
    Company.SearchParameters searchParams = new Company.SearchParameters(name);

    // Your logic here
}