依赖注入IOption类库

时间:2018-11-05 21:50:37

标签: c# asp.net-core dependency-injection

我有一个类库,我想在其中访问来自appsettings.json的Connectionstring。

appsettings.json:

"DatabaseSettings": {
    "ConnectionString": "Server=.;Database=Test;Trusted_Connection=True;"
  },

在startup.cs中,我有以下代码:

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<DatabaseSettings>(Configuration.GetSection("DatabaseSettings"));
    services.AddOptions();

    services.AddTransient<IConnectionOption, Class1>();
}

在类库中

IConnectionOption.cs

public interface IConnectionOption
{
    void ReadValue();
}

Class1.cs

public class Class1 : IConnectionOption
{
    private readonly DatabaseSettings test;

    public Class1(IOptions<DatabaseSettings> dbOptions)
    {
        test = dbOptions.Value;    
    }    

    public void ReadValue()
    {
        var r = test;
    }
}

现在从index.cshtml调用类库Class1

public class IndexModel : PageModel
{
    public void OnGet()
    {
        Class1 test = new Class1();
        test.ReadValue();
    }
}

但是,这当然不起作用,因为没有构造函数采用零参数,我认为我不应该将IOptions添加为参数。但是,如何调用类库以读取连接字符串? (当我使它起作用时,我当然会读取数据并返回,而不是返回连接字符串)。我看了几个例子,包括net core 2.1 Dependency injection 但是我不明白如何直接使用类库,是否需要使用控制器?!

2 个答案:

答案 0 :(得分:4)

如果类库可以访问DatabaseSettings,则实际上并不需要将Class1库紧密耦合到IOptions,这与框架更多相关。

理想情况下,Class1可以通过显式构造函数注入显式依赖DatabaseSettings

public class Class1 : IConnectionOption {
    private readonly DatabaseSettings test;

    public Class1(DatabaseSettings settings) {
        test = settings;    
    }    

    public void ReadValue() {
        var r = test;
        //...
    }
}

然后在Startup中,可以从配置中提取依赖项并在DI容器中注册

public void ConfigureServices(IServiceCollection services) {
    var settings = Configuration.GetSection("DatabaseSettings").Get<DatabaseSettings>();
    services.AddSingleton<DatabaseSettings>(settings);    
    services.AddTransient<IConnectionOption, Class1>();
}

这样,无论何时Class1被解决,容器都将知道如何注入DatabaseSettings依赖项。

另一个选择可能是使用工厂委托

public void ConfigureServices(IServiceCollection services) {
    var settings = Configuration.GetSection("DatabaseSettings").Get<DatabaseSettings>();
    services.AddTransient<IConnectionOption, Class1>(_ => new Class1(settings));
}

这样,当IndexModel依赖于IConnectionOption进行注入时。

public class IndexModel : PageModel {
    private readonly IConnectionOption connectionOption;

    public IndexModel(IConnectionOption iConnectionOption) {
        connectionOption = iConnectionOption;
    }

    public void OnGet() {
        connectionOption.ReadValue();
        //...
    }
}

初始化页面模型时,将注入适当的依赖项。

答案 1 :(得分:2)

您正在使用依赖注入,但仅在一半时使用。这就是你所缺少的:

  1. 在容器中注册服务(我将为echo "$b" | tr '{' '\n' | sed -rn 's/[^"]"(.*)".*/\1/p' | xargs -I xxx defaults write pbs NSServicesStatus -dict-add "xxx" " <dict> <key>enabled_context_menu</key><false/> <key>enabled_services_menu</key><false/> <key>key_equivalent</key><string>""</string> </dict>" 取一个更好的名称):

    Class1
  2. 使页面接收服务:

    services.AddScoped<IConnectionOption, DatabaseConnectionOption>();