我的应用程序使用了一堆Service类,其中许多都有一个支持Repository类。当我的应用程序启动时,我创建一个新的Unity容器,其句柄创建我的所有服务和存储库类,并执行所有依赖注入。我所看到的例子说,通过全局容器获取Unity容器是不好的做法,因此在完成创建所需的所有对象后,它会超出范围。创建。然后这些对象在程序的其余部分中传递。
我的问题是我有一个"设置"允许用户更改数据库名称和服务器的窗口。但是,所有Services对象都已具有通过注入原始数据库名称和服务器而创建的后备Repository对象。所以我必须为已经创建的所有Repository对象更改数据库连接字符串。
我正在考虑制作类似IDatabaseConnectionStringProxy
接口的东西,并让我的所有Repository对象都引用该类型的单个对象,而不是每个Repository存储其连接字符串明确性。然后我就可以拥有我的"设置" window更新所有Repository类指向的单个代理对象上的连接字符串。这是一个好的设计还是一个糟糕的做事方式?如果这不是一个好主意,我该如何处理?
答案 0 :(得分:4)
这听起来像my book中第272页所述的非常奇特的 Future 生活方式的变体。我认为你应该能够用Decorator来解决这个问题,而不是发明一个新的界面。
首先,让我们想象一下所涉及的类型是什么样的。听起来你有一些存储库接口。我们打电话给代表性的存储库IFooRepository
:
public interface IFooRepository
{
Foo Read(int id);
}
听起来你也有与数据库交谈的具体实现。为了更好地衡量,让我们给出具体的类Inspection Properties,以便我们可以查询存储库对象以询问它使用哪个连接字符串:
public class SqlFooRepository : IFooRepository
{
private const string connectionString;
public SqlFooRepository(string connectionString)
{
if (connectionString == null)
throw new ArgumentNullException("connectionString");
this.connectionString = connectionString;
}
public string ConnectionString
{
get { return this.connectionString; }
}
public Foo Read(int id)
{
// SQL query code goes here...
}
}
这使您可以创建装饰器(或者它可能是Decoraptor):
public class ConnectionstringAwareFooRepository : IFooRepository
{
private SqlFooRepository repo;
public Foo Read(int id)
{
var connectionstring =
ConfigurationManager.ConnectionStrings["foo"].ConnectionString;
if (this.repo == null ||
this.repo.ConnectionString != connectionString)
this.repo = new SqlFooRepository(connectionString);
return this.repo.Read(id);
}
}
这种设计的好处是它完全屏蔽了客户端代码,使其无法处理发现新连接字符串的管理方面。所有客户看到的都是IFooRepository
。
请注意,上述示例不是线程安全的。如果您需要在多线程环境中使用此解决方案,则需要使其成为线程安全的。
由于ConnectionstringAwareFooRepository
类从配置文件中读取,因此我强烈建议您将其与代码Composition Root放在代码库的同一部分。