Dependency injection 使用IoC处理在单个函数调用中更改的依赖项

Dependency injection 使用IoC处理在单个函数调用中更改的依赖项,dependency-injection,inversion-of-control,structuremap,Dependency Injection,Inversion Of Control,Structuremap,我们正试图找出如何设置依赖项注入,以适应服务类根据使用方式具有不同依赖项的情况。在我们的特定案例中,我们有一个web应用程序,其中95%的时间整个请求的连接字符串是相同的(这是一个web应用程序),但有时它可以更改 例如,我们可能有两个具有以下依赖项的类(简化版本-服务实际上有4个依赖项): 在我们的IoC容器中,我们的大多数依赖项都是自动连接的,除了上下文(不是实际的代码,它来自内存…这是StructureMap): x、 ForRequestedType()。使用() .WithTorArg

我们正试图找出如何设置依赖项注入,以适应服务类根据使用方式具有不同依赖项的情况。在我们的特定案例中,我们有一个web应用程序,其中95%的时间整个请求的连接字符串是相同的(这是一个web应用程序),但有时它可以更改

例如,我们可能有两个具有以下依赖项的类(简化版本-服务实际上有4个依赖项):

在我们的IoC容器中,我们的大多数依赖项都是自动连接的,除了上下文(不是实际的代码,它来自内存…这是StructureMap): x、 ForRequestedType()。使用() .WithTorArg(“连接字符串”).EqualTo(会话[“连接字符串])

对于我们95%的web应用程序来说,这是完美的。但是,我们有一些管理类型的函数,必须跨数千个数据库(每个客户端一个)运行。基本上,我们希望这样做:

public CreateUserList(IList<string> connStrings)
{
   foreach (connString in connStrings)
   {
       //first create dependency graph using new connection string 
       ????       
       //then call service method on new database
       _loginService.GetReportDataForAllUsers();
   }
}
publicCreateUserList(IList字符串)
{
foreach(connString中的connString)
{
//首先使用新的连接字符串创建依赖关系图
????       
//然后在新数据库上调用服务方法
_loginService.GetReportDataForAllUsers();
}
}

我的问题是:如何在每次循环中创建新的依赖关系图,同时维护易于测试的内容?

要将对象的创建推迟到运行时,可以使用工厂:

public interface ILoginServiceFactory
{
    ILoginService CreateLoginService(string connectionString);
}
用法:

public void CreateUserList(IList<string> connStrings)
{
    foreach(connString in connStrings)
    {
        var loginService = _loginServiceFactory.CreateLoginService(connString);

        loginService.GetReportDataForAllUsers();
    }
}
public void CreateUserList(IList字符串)
{
foreach(connString中的connString)
{
var loginService=_loginServiceFactory.CreateLoginService(connString);
loginService.GetReportDataForAllUsers();
}
}
在循环中,执行以下操作:

container.With("connectionString").EqualTo(connString).GetInstance<ILoginService>()
container.With(“connectionString”).EqualTo(connString.GetInstance())

其中,“connectionString”是ILoginService的具体实现上的字符串构造函数参数的名称。

因此大多数
UserRepository
方法使用从会话中获得的单个连接字符串,但有几个方法需要对连接字符串列表进行操作

您可以通过将连接字符串依赖项从
IContext
提升到存储库并添加两个附加依赖项来解决此问题—一个上下文工厂和存储库可能需要执行其工作的所有可能连接字符串的列表:

public UserRepository(IContextFactory contextFactory, 
                      string          defaultConnectionString, 
                      List<string>    allConnectionStrings)

我们最终只是创建了一个具体的上下文并将其注入,然后创建了一个包装器类,该类改变了上下文的连接字符串。看起来很好。

我们如何将其与IoC容器混合使用,有什么想法吗?在我们的例子中,我们有一个相当大的依赖关系图(我上面给出的示例非常简化),手动管理许多依赖关系听起来并不有趣。+1如果所有相关方法都不返回数据,那么一个好的替代方法是创建一个负责遍历所有连接字符串的组合。Mark-你能说得更多吗?我们的难题是让现有的服务/存储库方法与发生变化的数据库上下文一起工作。您可以使用容器而不是ObjectFactory吗?虽然我不确定在不完全重置依赖关系图的情况下如何交换上下文对象(这可能需要很长时间)。我们需要在所有服务/存储库中共享单个上下文,而不仅仅是在单个上下文中使用。考虑到这一点,重建整个图形是最好的吗?
public UserRepository(IContextFactory contextFactory, 
                      string          defaultConnectionString, 
                      List<string>    allConnectionStrings)
// In UserRepository

public CreateUserList() {
    foreach (string connString in allConnectionStrings) {
        IContext context = contextFactory.CreateInstance(connString);
        // Build the rest of the dependency graph, etc. 
        _loginService.GetReportDataForAllUsers();
    }
}

public LoginUser() {
    IContext context = contextFactory.CreateInstance(defaultConnectionString);
    // Build the rest of the dependency graph, etc.
}