【问题标题】:How to read configuration values from AppSettings and inject the configuration to instances of interface如何从 AppSettings 读取配置值并将配置注入接口实例
【发布时间】:2017-04-19 10:49:07
【问题描述】:

就在最近,我一直在尝试新的 asp.net 功能并遇到了这个问题。 我知道我们可以将配置读取为强类型实例。但我不知道如何在 Microsoft 依赖注入中将配置注入我的类。

public interface IProvider
{
  IMyConfiguration Configuration {get;}
  Task Connect();
}

public abstract class Provider: IProvider
{
    private IMyConfiguration _myConfig;

    public Provider(IMyConfiguration config)
    {
        this._myConfig= config;
    }

    public IMyConfiguration Configuration => _myConfig;
    public abstract Task Connect();
}

public class ProviderOne:Provider
{
    public ProviderOne(IMyConfiguration  config) : base(config)
    {
    }

    public Task Connect()
    {
      //implementation
    }
}

配置类:

public interface IMyConfiguration
{
     string TerminalId { get;set; }
     bool IsDefault {get;set;}
}
public class MyConfiguration : IMyConfiguration
{
     string TerminalId { get;set; }
     bool IsDefault {get;set;}
}

然后在我声明的 startup.cs 中,需要通过 MyConfiguration。但我找不到这样做的方法。请指教!

public void ConfigureServices(IServiceCollection services)
{
  services.Configure<MyConfiguration>(Configuration.GetSection("MyConfiguration"));
  services.AddSingleton<IProvider>(new ProviderOne(//configuration)); //here is the problem
}

【问题讨论】:

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


    【解决方案1】:

    选项 1

    首先,你不需要IMyConfiguration 接口。 .NET Core 已经使用自己的 IOptions 接口进行抽象。当你使用

    services.Configure<MyConfiguration>(Configuration.GetSection("MyConfiguration"));
    

    你告诉 DI 如何解决下一个依赖:IOptions&lt;MyConfiguration&gt;

    所以,而不是

    public Provider(IMyConfiguration config)
    

    使用

    private MyConfiguration _myConfig;
    
    public Provider(IOptions<MyConfiguration> options)
    {
        this._myConfig = options.Value;
    }
    

    ProviderOne 也一样

    public ProviderOne(IOptions<MyConfiguration> options) : base(options)
    

    由于 .NET Core DI 知道如何解析已注册的依赖项,现在您可以简单地使用该方法的下一个版本:

    services.AddSingleton<IProvider, ProviderOne>();
    

    选项 2

    您可以保留您的代码原样;在ConfigureServices 方法中直接实例化MyConfiguration 的实例并用于ypur Provider 实例的创建:

    var myConfiguration = new MyConfiguration();
    Configuration.GetSection("MyConfiguration").Bind(myConfiguration);
    
    services.AddSingleton<IProvider>(new ProviderOne(myConfiguration));
    

    主要区别在于,在这种情况下,您不会将 DI 容器用于 ProviderOne 实例化。所以主要的缺点是,如果您需要为您的提供者添加更多依赖项(并因此扩展构造函数参数的数量),您也应该在 ConfigureServices 方法中解决这些依赖项。有关更多详细信息,您可能会发现下一个讨论很有用:Best way to resolve during ConfigureServices

    一般来说,当你只有一个IMyConfiguration 的实现时,也可以这样做:

    services.AddSingleton<IMyConfiguration>(myConfiguration);
    services.AddSingleton<IProvider, ProviderOne>();
    

    DI 容器将了解如何处理它。但是由于内置的​​ DI 容器不允许注册多个服务然后检索特定的服务,所以这不适合您。有些人通过使用工厂模式来解决这个问题。您将在下一个 SO 问题中找到更多信息:How to register multiple implementations of the same interface in Asp.Net Core?

    【讨论】:

    • 很好,但是有一个问题,假设我们有不同的 MyConfiguration 和 Provider 实例,每个提供程序应该如何连接到它的配置。
    • @Behzad 好的,我添加了选项 2
    • 这样做好吗?我的意思是,我真的很想在我的应用中使用最佳实践
    • @Behzad 如果简短,请尽可能使用 DI,而不是手动实例化。您的主要问题是您有多个IMyConfiguration 接口的实现,但内置的 ASP.NET Core DI 容器不支持注册多个服务然后检索特定服务。我已经更新了答案,如果你真的有很多不同的 IMyConfiguration 实现,我建议考虑使用一些额外的自己的工厂类进行配置实例化。
    • @Behzad 你也可以在你的应用程序中使用非默认 IoC,它支持命名依赖项。
    【解决方案2】:
    1. 创建一个具有必须从 appsettings 读取的属性的类

    Appsettings.json

    {
    "DecoderClientOptions":
      {
         "url":"someurl@example.com",
         "key":"A90474-kGAAP1"
      }
    }
    

    1.创建模型类。

         public class DecoderClientOptions
            {
                public string url { get; set; }
                public int key { get; set; }
            }
    
    1. 在 Startup.cs 中注入依赖

           services.Configure<DecoderClientOptions> 
           (Configuration.GetSection(nameof(DecoderClientOptions)));
      
    2. 使用其他类中的属性

          public class DecoderClient : IDecoderClient
          {      
              private readonly IOptions<DecoderClientOptions> _ClientOptions;
      
              public DecoderClient(IOptions<DecoderClientOptions> ClientOptions)
              {
                  _ClientOptions = ClientOptions;
              }
      
            var url = _ClientOptions.Value.url;
            var key = _ClientOptions.Value.key;
      

    【讨论】:

      猜你喜欢
      • 2017-02-14
      • 1970-01-01
      • 1970-01-01
      • 2018-02-06
      • 2017-03-03
      • 1970-01-01
      • 2017-08-22
      • 1970-01-01
      • 2020-06-02
      相关资源
      最近更新 更多