Reputation: 13397
I have this config file:
public class Config: IDataConfig, IIdentityServerConfig, IStorageConfig
{
public string ConnectionString { get; set; }
public string Authority { get; set; }
public string AzureStorageConnectionString { get; set; }
}
And in one of my classes, I have this:
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);
}
As you can see, it expects an instance of IStorageConfig
to be passed to it.
In the old days, you would use autofac and register the config as all implemented interfaces.
In .net core, I would like to know how to do that. Currently I have this:
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; });
}
Does anyone know how I can achieve what I am after?
Here is my appsettings file:
{
"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": "*"
}
Upvotes: 2
Views: 1457
Reputation: 247591
The following assumption is based on the definition and use of Config
class in the original example
public interface IDataConfig {
string ConnectionString { get; set; }
}
public interface IIdentityServerConfig {
string Authority { get; set; }
}
public interface IStorageConfig {
string AzureStorageConnectionString { get; set; }
}
So given
public class Config: IDataConfig, IIdentityServerConfig, IStorageConfig {
public string ConnectionString { get; set; }
public string Authority { get; set; }
public string AzureStorageConnectionString { get; set; }
}
That type would require each interface to be registered.
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
There really should not be any need to manually build the service provider within Startup but for your example the provider can be accessed for the DbContext
registration using the following AddDbContext
overload that defers invocation and accesses a IServiceProvider
.
//...
services.AddDbContext<DatabaseContext>((serviceProvider, options) =>
options.UseSqlServer(serviceProvider.GetRequiredService<IDataConfig>().ConnectionString)
);
//...
Upvotes: 3