使用 IoC 处理在单个函数调用中发生变化的依赖关系
我们正在尝试找出如何在服务类根据其使用方式具有不同依赖项的情况下设置依赖项注入。在我们的具体案例中,我们有一个 Web 应用程序,其中 95% 的情况下整个请求的连接字符串是相同的(这是一个 Web 应用程序),但有时它可能会发生变化。
例如,我们可能有 2 个具有以下依赖项的类(简化版本 - 服务实际上有 4 个依赖项):
public LoginService (IUserRepository userRep)
{
}
public UserRepository (IContext dbContext)
{
}
在我们的 IoC 容器中,大多数依赖项都是自动连接的,除了我有类似这样的上下文(不是实际代码) ,这是从记忆中...这是 StructureMap): x.ForRequestedType().Use() .WithCtorArg("connectionString").EqualTo(Session["ConnString"]);
对于我们 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();
}
}
我的问题是:我们如何为每次循环创建新的依赖关系图,同时维护可以轻松测试的内容?
We are trying to figure out how to setup Dependency Injection for situations where service classes can have different dependencies based on how they are used. In our specific case, we have a web app where 95% of the time the connection string is the same for the entire Request (this is a web application), but sometimes it can change.
For example, we might have 2 classes with the following dependencies (simplified version - service actually has 4 dependencies):
public LoginService (IUserRepository userRep)
{
}
public UserRepository (IContext dbContext)
{
}
In our IoC container, most of our dependencies are auto-wired except the Context for which I have something like this (not actual code, it's from memory ... this is StructureMap):
x.ForRequestedType().Use()
.WithCtorArg("connectionString").EqualTo(Session["ConnString"]);
For 95% of our web application, this works perfectly. However, we have some admin-type functions that must operate across thousands of databases (one per client). Basically, we'd want to do this:
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();
}
}
My question is: How do we create that new dependency graph for each time through the loop, while maintaining something that can easily be tested?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
要将对象的创建推迟到运行时,您可以使用工厂:
用法:
To defer the creation of an object until runtime, you can use a factory:
Usage:
在循环内,执行:
其中“connectionString”是 ILoginService 具体实现上的字符串构造函数参数的名称。
Within the loop, do:
where "connectionString" is the name of a string constructor parameter on the concrete implementation of ILoginService.
所以大多数
UserRepository
方法使用从会话获取的单个连接字符串,但是有几个方法需要针对连接字符串列表进行操作?您可以通过将连接字符串依赖项从
IContext
提升到存储库并添加两个附加依赖项来解决此问题 - 一个上下文工厂和存储库完成其工作可能需要的所有可能连接字符串的列表:然后它的每个方法都可以根据需要构建任意数量的
IContext
实例:So most
UserRepository
methods use a single connection string obtained from session, but several methods need to operate against a list of connection strings?You can solve this problem by promoting the connection string dependency from
IContext
to the repository and adding two additional dependencies - a context factory and a list of all the possible connections strings the repository might need to do its work:Then each of its methods can build as many
IContext
instances as they need:我们最终只是创建一个具体的上下文并注入它,然后更改创建一个更改上下文连接字符串的包装类。看起来效果很好。
We ended up just creating a concrete context and injecting that, then changing creating a wrapper class that changed the context's connection string. Seemed to work fine.