我掌握了依赖注入的基础知识,但我正在努力将其整合到一个使用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>
答案 0 :(得分:0)
我在这里看到两个任务。第一个是重构,其中静态依赖项必须用接口替换。第二个任务是在IoC容器中注册你的东西。
对于第一项任务,您至少需要将Database
中UserSearchService
的所有引用替换为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
}