C# 使用带运行时参数的构造函数的Unity依赖注入

C# 使用带运行时参数的构造函数的Unity依赖注入,c#,asp.net-mvc,dependency-injection,dependencies,unity-container,C#,Asp.net Mvc,Dependency Injection,Dependencies,Unity Container,我已经掌握了依赖注入的基本知识,但我正在努力使用Unity将其正确地整合到MVCAPI应用程序中。我的问题是,我将有一个控制器,它有一个方法,在这个方法中,它将有两个对象。其中一个对象将依赖于数据访问层,而另一个对象则不依赖。我不太清楚如何设置这个 假设我有一个控制器,它使用以下方法从搜索对象获取用户。它还使用SearchParameters对象来执行搜索。如果你搜索时没有名字,你会得到所有的结果,或者如果你输入了一个名字,你会得到任何有这个名字的用户 public Users[] GetUse

我已经掌握了依赖注入的基本知识,但我正在努力使用Unity将其正确地整合到MVCAPI应用程序中。我的问题是,我将有一个控制器,它有一个方法,在这个方法中,它将有两个对象。其中一个对象将依赖于数据访问层,而另一个对象则不依赖。我不太清楚如何设置这个

假设我有一个控制器,它使用以下方法从搜索对象获取用户。它还使用SearchParameters对象来执行搜索。如果你搜索时没有名字,你会得到所有的结果,或者如果你输入了一个名字,你会得到任何有这个名字的用户

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

    return searchService.Search();
}
这当然是一个超级简化的版本,但在本例中,搜索方法中的UserSearchService正在执行显式数据库调用。所以我知道这是我必须给予它的依赖。SearchParameters实际上只是一个保存数据的类

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


此外,SearchParameters和UserSearchService没有任何类型的支持接口(如果这很重要),并且此控制器上的其他方法与其他类交互,这些类具有类似的数据访问层依赖性需求,例如Company.UserAccount。

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

对于第一个任务,您至少需要将
UserSearchService
中对
数据库的所有引用替换为
IDatabase
接口(这样它也可以被模拟),并允许将其传递给构造函数(构造函数注入)。为了能够向服务提供
IDatabase
的实例,您必须为控制器创建相同的依赖项(同样是构造函数注入)。然后注册
IDatabase
实现,如中所示

更新

我同意必须从控制器中删除依赖项。正如@Topojijo所建议的,在这种情况下可以使用
UserSearchService
的工厂。假设你有几个子宫颈,你需要为每个都建立一个工厂,如果它们的数量很大,可能会有一笔开销。在这种情况下,最好从Unity容器中将
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);
}
public Users[]GetUsers(字符串名称){
Company.SearchParameters searchParams=新公司.SearchParameters(名称);
Company.UserSearchService searchService=container.Resolve();
返回searchService.Search(searchParams);
}

搜索参数不应该是构造函数的一部分;它应该是“搜索”方法的一部分。SearchParameter对象甚至不应该在UserSearchService类(封装)之外被知道。应该按照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);
}
公司。用户搜索服务:

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
}

根据您的代码,
公司.UserSearchService
除了
公司.SearchParameters
(或者您遗漏了什么?)但是你说控制器本身没有依赖项,但是由于UserSearchService没有在UserSearchService的搜索方法中执行,它有一个对Database.Execute的显式调用,Database.Execute是一个访问数据库的静态方法,所以依赖项当前所在的位置。我想解决这个问题,使它实际上是可测试的。这是我起初的想法,但后来我读到,将依赖项传递给控制器是错误的,因为控制器本身从未使用该依赖项。我所看到的是控制器通过了一个构建UserSearchService的工厂,该工厂使用Unity。是的,这是一个更高级的解决方案。我已经更新了我的答案。