【问题标题】:.net core resolve config interface.net core 解析配置界面
【发布时间】:2019-09-26 19:42:16
【问题描述】:

我有这个配置文件:

public class Config: IDataConfig, IIdentityServerConfig, IStorageConfig
{
    public string ConnectionString { get; set; }
    public string Authority { get; set; }
    public string AzureStorageConnectionString { get; set; }
}

在我的一堂课中,我有这个:

public class StorageClient : IStorageClient
{
    private readonly CloudBlobClient _blobClient;

    public StorageClient(IStorageConfig config)
    {
        var storageAccount = CloudStorageAccount.Parse(config.AzureStorageConnectionString);
        _blobClient = storageAccount.CreateCloudBlobClient();
    }

    public CloudBlobContainer GetContainerReference(string name) => _blobClient.GetContainerReference(name);
}

如您所见,它希望将IStorageConfig 的实例传递给它。 在过去,您会使用 autofac 并将配置注册为所有已实现的接口。

在 .net 核心中,我想知道如何做到这一点。目前我有这个:

public void ConfigureServices(IServiceCollection services)
{
    services.AddCors(m => m.AddPolicy("AllowAll", o => o.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod()));

    services.Configure<Config>(Configuration.GetSection("ConnectionStrings"));
    services.Configure<Config>(Configuration.GetSection("Options"));
    services.Configure<CookiePolicyOptions>(options =>
    {
        // This lambda determines whether user consent for non-essential cookies is needed for a given request.
        options.CheckConsentNeeded = context => true;
        options.MinimumSameSitePolicy = SameSiteMode.None;
    });

    var buildServiceProvider = services.BuildServiceProvider();
    var config = buildServiceProvider.GetService<IOptions<Config>>();

    services.AddTransient(typeof(IGenericService<>), typeof(GenericService<>));
    services.AddTransient<IContainerProvider, ContainerProvider>();

    services.AddSingleton<IComparer, Comparer>();
    services.AddSingleton<IDataTypeFactory, DataTypeFactory>();
    services.AddSingleton<IFilterProvider, FilterProvider>();
    services.AddSingleton<IJsonClient, JsonClient>();
    services.AddSingleton<INumericFactory, NumericFactory>();
    services.AddSingleton<IStorageClient, StorageClient>();
    services.AddSingleton<IStringFactory, StringFactory>();
    services.AddSingleton<IValidator, Validator>();
    services.AddSingleton<HttpClient>();

    services.AddDbContext<DatabaseContext>
        (options => options.UseSqlServer(config.Value.ConnectionString));
    services.AddSwaggerGen(options =>
        {
            options.SwaggerDoc("v1", new Info {Title = "Situ Experience Platform API", Version = "v1"});
            options.IncludeXmlComments($"{System.AppDomain.CurrentDomain.BaseDirectory}\\Api.xml");
        });
    services.AddAuthentication("Bearer")
        .AddIdentityServerAuthentication(options =>
        {
            options.Authority = config.Value.Authority;
            options.RequireHttpsMetadata = false;
            options.ApiName = "Sxp";
        });
    services.AddMvc()
        .ConfigureApiBehaviorOptions(options => { options.SuppressModelStateInvalidFilter = true; });
}

有谁知道我怎样才能实现我所追求的目标?

这是我的 appsettings 文件:

{
  "ConnectionStrings": {
    "ConnectionString": "Server=localhost;Database=sxp_master;Trusted_Connection=True;",
    "Storage": "DefaultEndpointsProtocol=https;AccountName=sxp;AccountKey=moo"
  },
  "Options": {
    "Authority": "https://localhost:44362"
  },
  "Logging": {
    "Debug": {
      "LogLevel": {
        "Default": "Information"
      }
    },
    "Console": {
      "IncludeScopes": false,
      "LogLevel": {
        "Microsoft.AspNetCore.Mvc.Razor.Internal": "Warning",
        "Microsoft.AspNetCore.Mvc.Razor.Razor": "Debug",
        "Microsoft.AspNetCore.Mvc.Razor": "Error",
        "Default": "Information"
      }
    },
    "LogLevel": {
      "Default": "Debug"
    }
  },
  "AllowedHosts": "*"
}

【问题讨论】:

  • @Nkosi 它不会覆盖,而是将它们添加到集合中。但这不是这里的问题。我希望能够注入我的配置接口而不是做IOptions&lt;Config&gt;,因为我不想/喜欢注入具体的类。特别是因为其中一些类“可能”是外部的。
  • 好的,我会删除该评论。根据更新,我可以看到 ConnectionStringAuthority 来自哪里,但不是 AzureStorageConnectionString
  • 我什至会满足于IOptions&lt;IStorageConfig&gt; 但不,IOptions 要求对象具有构造函数(无参数)

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


【解决方案1】:

以下假设是基于原示例中Config类的定义和使用

public interface IDataConfig {
    string ConnectionString { get; set; }
}

public interface IIdentityServerConfig {
    string Authority { get; set; }
}

public interface IStorageConfig {
    string AzureStorageConnectionString { get; set; }
}

所以给定

public class Config: IDataConfig, IIdentityServerConfig, IStorageConfig {
    public string ConnectionString { get; set; }
    public string Authority { get; set; }
    public string AzureStorageConnectionString { get; set; }
}

该类型需要注册每个接口。

services.AddCors(m => m.AddPolicy("AllowAll", o => 
    o.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod()));

services.Configure<Config>(Configuration.GetSection("ConnectionStrings"));
services.Configure<Config>(Configuration.GetSection("Options"));
services.Configure<CookiePolicyOptions>(options =>
{
    // This lambda determines whether user consent for 
    // non-essential cookies is needed for a given request.
    options.CheckConsentNeeded = context => true;
    options.MinimumSameSitePolicy = SameSiteMode.None;
});

//register the individual interfaces, extracting the registered IOptions<Config>
services.AddSingleton<IDataConfig>(sp => sp.GetRequiredService<IOptions<Config>>().Value);
services.AddSingleton<IIdentityServerConfig>(sp => sp.GetRequiredService<IOptions<Config>>().Value);
services.AddSingleton<IStorageConfig>(sp => sp.GetRequiredService<IOptions<Config>>().Value);

//...omitted for brevity

确实不需要在 Startup 中手动构建服务提供者,但对于您的示例,可以使用以下 AddDbContext overload 访问提供者以进行 DbContext 注册,该 AddDbContext overload 延迟调用并访问 IServiceProvider

//...

services.AddDbContext<DatabaseContext>((serviceProvider, options) => 
    options.UseSqlServer(serviceProvider.GetRequiredService<IDataConfig>().ConnectionString)
);

//...

【讨论】:

  • 很好的假设:)
猜你喜欢
  • 1970-01-01
  • 2020-01-02
  • 2022-11-02
  • 1970-01-01
  • 2022-12-20
  • 2023-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多