连接字符串代理?

Connection String Proxy?

我的应用程序使用了一堆服务 classes,其中许多都有一个支持存储库 class。当我的应用程序启动时,我创建了一个新的 Unity 容器,其中包含创建我所有服务和存储库 classes 的句柄,并执行所有依赖项注入。我看到的示例表明,通过全局容器拥有 Unity 容器是一种不好的做法,因此它在创建完所有需要创建的对象后就超出了范围。然后这些对象会在程序的其余部分传递。

我的问题是我有一个 "settings" window 允许用户更改数据库名称和服务器。但是,所有服务对象都已经具有通过注入原始数据库名称和服务器创建的支持存储库对象。因此,我必须更改所有已创建的 Repository 对象的数据库连接字符串。

我正在考虑制作类似 IDatabaseConnectionStringProxy 接口的东西,并让我的所有 Repository 对象都引用该类型的单个对象,而不是每个 Repository 显式存储其连接字符串。然后我可以让我的 "settings" window 更新所有存储库 classes 都指向的单个代理对象上的连接字符串。这是好的设计还是糟糕的做事方式?如果这不是一个好主意,我应该如何处理?

这听起来像是 my book. Instead of inventing a new interface, I think you should be able to address this concern with a Decorator.

第 272 页中描述的充满异国情调的 未来 生活方式的变体

首先,让我们想象一下涉及的类型是什么样的。听起来您有一些存储库接口。让我们调用一个有代表性的 Repository IFooRepository:

public interface IFooRepository
{
    Foo Read(int id);
}

听起来您还有与数据库对话的具体实现。为了更好地衡量,让我们给出具体的 classes 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 class 从配置文件中读取,我强烈建议您将它放在与 Composition Root.[=20 相同的代码库中=]