【问题标题】:Dependency Injection With Interface but Constructor Needs String Parameter使用接口进行依赖注入,但构造函数需要字符串参数
【发布时间】:2019-01-28 13:48:07
【问题描述】:

我有一个存储库类,它有一个带有字符串参数参数的构造函数。它是一个连接字符串。我为它创建了一个界面,并在我的 UI 项目中使用 Unity。

我的问题是,如何以“正确”的方式进行设置,以便 Unity 知道如何正确构造我的类,以便在实例化我的控制器时注入它?

我目前通过为我的存储库使用无参数构造函数来“解决”这个问题,但感觉这是一种逃避。

这是我要使用的存储库构造函数...

    public CobraLettersRepository(string dbConnectionString)
    {
        _connString = dbConnectionString ?? throw new ArgumentNullException(dbConnectionString);

        dbConnection = new SqlConnection(_connString);
        dbConnection.Open();
    }

我创建了 ICobraLettersRepository 并希望将其注入到我的控制器构造函数中。

    public CobraLetterController(ICobraLetterRepository cobraLetterRepository)
    {
        if (cobraLetterRepository == null)
            throw new ArgumentNullException(cobraLetterRepository);

        _cobraLetterRepo = cobraLetterRepository;
    }

当我尝试此操作时,代码会编译,但每当我尝试导航到调用这些控制器方法的应用程序部分时都会出现运行时错误。

【问题讨论】:

  • “我得到运行时错误” 哪些?请更具体地说明您的问题。从我的角度来看,假设CobraLettersRepository 实现了ICobraLetterRepository,您的代码还可以。除此之外:你肯定想要ArgumentNullException(nameof(dbConnectionString))
  • 您可以提供一个func,它将一个对象的实例返回给服务,例如services.AddScoped((IServiceProvider) => new SQLLogger(connectionString));
  • 在构造函数中打开连接是一个主要错误。连接应该只在它们被使用之前被创建和打开,然后在之后被释放。长连接唯一能做的就是积累锁并导致阻塞。反复打开/关闭连接并没有没有的惩罚,实际上它通过连接池提高了性能。

标签: c# model-view-controller dependency-injection unity-container


【解决方案1】:

我会说将连接字符串封装在配置对象中,并将连接字符串的获取放入该配置对象的构造函数中。 然后只需将您的配置对象注册为其他类。

public class ProjectConfiguration
{
    public string ConnectionString { get; set; }

    public ProjectConfiguration()
    {
        ConnectionString = //Get the configuration from , i.e: ConfigurationManager
    }

}

然后,注入它:

public CobraLettersRepository(ProjectConfiguration configuration)
{
    if(configuration == null){
        throw new ArgumentNullException(configuration);
    }
    _connString = configuration.ConnectionString;

    dbConnection = new SqlConnection(_connString);
    dbConnection.Open();
}

这样,您始终可以将配置与 DI 容器隔离开来,并使注入尽可能简单。此外,您可以从配置文件中获取配置(每个环境一个)。

编辑:还要检查您的存储库构造函数逻辑,也许您不想在构造函数上打开连接。最好在类方法上使用 using 语句,例如:

using(SqlConnection connection = new SqlConnection(_injectedConfiguration.ConnectionString)){
    connection.Open();
    //Make your stuff here
}

通过使用,您可以确保正确处理连接。

请注意,使用配置对象方法,您可以将配置对象存储在私有只读变量中,并根据需要使用它。

【讨论】:

  • 啊..好点。在构造函数中打开数据库连接可能不合适。我正在研究的解决方案有许多可以执行此操作的存储库。在构造函数中打开,在 Dispose 方法中实现 IDisposable,关闭和处理连接。
【解决方案2】:

在注册过程中,使用InjectionConstructor 传递连接字符串名称。您需要删除所有构造函数,除了需要 string 参数的构造函数。

container.RegisterType<ICobraLetterRepository,CobraLettersRepository>(new InjectionConstructor("connectionstringname"));

请注意,它会在某处/某时导致问题。您需要更改创建数据库连接的逻辑(您可以参考Breaking SOLID Principles in multiple implementation of an InterfaceResolve named registration dependency in Unity with runtime parameter)。

【讨论】:

    猜你喜欢
    • 2023-03-08
    • 2017-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多