C# 连接字符串代理?

C# 连接字符串代理?,c#,dependency-injection,unity-container,C#,Dependency Injection,Unity Container,我的应用程序使用了一组服务类,其中许多都有一个支持存储库类。当我的应用程序启动时,我创建一个新的Unity容器,其中包含创建所有服务和存储库类的句柄,并执行所有依赖项注入。我看到的示例表明,将Unity容器放在全局容器中是一种不好的做法,因此在创建完需要创建的所有对象后,它就超出了范围。然后这些对象会在程序的其余部分传递 我的问题是,我有一个设置窗口,允许用户更改数据库名称和服务器。但是,所有服务对象都已具有通过注入原始数据库名称和服务器创建的备份存储库对象。因此,我必须更改所有已创建的存储库对

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

我的问题是,我有一个设置窗口,允许用户更改数据库名称和服务器。但是,所有服务对象都已具有通过注入原始数据库名称和服务器创建的备份存储库对象。因此,我必须更改所有已创建的存储库对象的数据库连接字符串


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

这听起来像是中第272页描述的非常奇特的未来生活方式的变体。我认为您不应该发明一个新的接口,而应该能够用一个新的接口解决这个问题

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

听起来您还有与数据库对话的具体实现。为了更好地衡量,让我们给出具体的类,以便我们可以查询repository对象,询问它使用哪个连接字符串:

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...
    }
}
这使您能够创建装饰器,或者它可能是:

这种设计的好处是,它完全屏蔽了客户端代码,使其无法处理发现新连接字符串的管理方面的问题。客户端只看到IFooRepository

但是请注意,上面的示例不是线程安全的。如果需要在多线程环境中使用此解决方案,则需要使其具有线程安全性


由于ConnectionStringawareForepository类从配置文件中读取,因此我强烈建议您将其放在代码库的同一部分中,与您的相同。

在请求用户输入之前创建这些对象是否有意义?在用户更改设置之前是否使用默认连接字符串?是的,默认情况下,程序是使用默认连接字符串安装的。然后,如果用户更改了连接,那么在下次启动程序时,该数据库名称和服务器将成为新的默认值。程序所做的几乎所有事情都需要数据库访问,因此它需要从启动时创建这些对象。下次启动程序时,您不能将新的连接字符串保存在配置文件中并继续吗?我会将其保存在那里。下次程序启动时,我没有问题,因为所有依赖项注入都是重新完成的,一切都很好。我的困难在于在程序执行期间更新存储在每个存储库对象中的所有连接字符串。这是一个有趣的解决方案。我以前也从未听说过“未来生活方式”这个词。谢谢你介绍给我。我要读一读。我有点担心ConnectionStringawareForepository中的ConfigurationManager引用,特别是它是一个静态类,因为我一直在努力确保所有依赖项都被注入,而ConfigurationManager看起来像是引入了外部依赖项。在您看来,这种类型的配置设置外部依赖性可以吗?@BenRubin这就是为什么我建议您将该类放在组合根目录中。您需要从某个地方的.config文件中读取配置值,而该地方是合成根。@BenRubin如果您更愿意将ConnectionStringawareForepository放在其他地方,那么请插入一个可以为您读取连接字符串的抽象工厂,并通过读取配置文件来实现该抽象工厂。因此,在您的示例中,ConfigurationManager是存储库的一个属性,表示ConfigurationManager.ConnectionString[foo]。ConnectionString使其从应用程序的配置中读取当前值,而不是程序读取组合根上的连接字符串并缓存该值。对吗?抱歉问了这么多问题;易居 我想确保我能很好地理解这一点。@BenRubin ConfigurationManager是。。。
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...
    }
}
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);
    }
}