[英]Can't access all extension methods for IApplicationBuilder outside of Startup.cs
[英]Cleaning up startup.cs with extension methods?
我通過允許根據用戶 cookie 更改 connectionString 來配置我的數據庫上下文:
services.AddDbContext<HotdogContext>((serviceProvider, dbContextBuilder) =>
{
string connectionString = "DatabaseUS"; // Default connection string
var httpContextAccessor = serviceProvider.GetRequiredService<IHttpContextAccessor>();
var dbNameCookie = httpContextAccessor.HttpContext.Request.Cookies.ContainsKey("country");
if (dbNameCookie) // debug
{
Console.Write("Country cookie exists!");
}
var country = httpContextAccessor.HttpContext.Request.Cookies["country"]?.ToString() ?? "null";
if (country.Equals("null"))
{
Console.WriteLine("Country cookie is null");
}
else if (country.Equals("USA"))
{
Console.WriteLine("Set USA connection string");
connectionString = "DatabaseUS";
}
else if (country.Equals("AUS"))
{
connectionString = "DatabaseAUS";
Console.WriteLine("Set Australia connection string");
}
else if (country.Equals("S.A."))
{
//connectionString = "DatabaseSA";
Console.WriteLine("Set South America connection string");
}
dbContextBuilder.UseSqlServer(Configuration.GetConnectionString(connectionString));
});
如果我向程序添加額外的 databaseContexts,這會使 startup.cs 變得混亂。 有沒有辦法可以從 startup.cs 隱藏這個邏輯並使用擴展方法?
services.AddDbContext<HotdogContext>((serviceProvider, dbContextBuilder) =>
{
string connectionString = "DatabaseUS"; // Default connection string
var httpContextAccessor = serviceProvider.GetRequiredService<IHttpContextAccessor>();
var country = dbContextBuilder.GetRequestedCountry(httpContextAccessor); // Extension method
if(country !=null) connectionString = country;
dbContextBuilder.UseSqlServer(Configuration.GetConnectionString(connectionString));
});
一種方法是定義一個服務接口,然后用你的邏輯實現:
public interface IConnectionStringNameService
{
string GetName();
}
public class ConnectionStringNameFromCookieService
: IConnectionStringNameService
{
private readonly HttpContext _httpContext;
public ConnectionStringNameFromCookieService(
HttpContextAccessor httpContextAccessor )
{
_httpContext = httpContextAccessor.HttpContext;
}
public string GetName()
{
var country = _httpContext.Request
.Cookies[ "country" ]
?? "default value"; // or throw exception
return country switch =>
{
"USA" => "DatabaseUS",
"AUS" => "DatabaseAUS",
"S.A." => "DatabaseSA",
_ => "Default name or throw",
}
}
}
然后向容器注冊服務實現:
services.AddScoped<IConnectionStringNameService, ConnectionStringNameFromCookieService>();
然后,當您需要連接字符串名稱時,您可以從服務提供商處解析此服務:
var connStrNameSvc = serviceProvider.GetRequiredService<IConnectionStringNameService>.();
var connStrName = connStrNameSvc.GetName();
就地(在啟動文件中),上面將抽象為:
services.AddDbContext<HotdogContext>(
(serviceProvider, dbContextBuilder) =>
{
var connStrName = serviceProvider
.GetRequiredService<IConnectionStringNameService>()
.GetName();
dbContextBuilder.UseSqlServer(
Configuration.GetConnectionString( connStrName ) );
});
但是您可以使用擴展方法將此調用抽象為一條簡單的行:
public class BlahBlahExtensionMethods
{
// come up with a better name
public IServiceCollection AddDbContextUsingCookieForConnStrName<TDbContext>(
this IServiceCollection services )
where TDbContext : DbContext
{
return services.AddDbContext<TDbContext>(
( serviceProvider, dbContextBuilder ) =>
{
var connStrName = serviceProvider
.GetRequiredService<IConnectionStringNameService>()
.GetName();
dbContextBuilder.UseSqlServer(
Configuration.GetConnectionString( connStrName ) );
});
}
}
然后在啟動時你只需要:
services.AddDbContextUsingCookieForConnStrName<HotdogContext>();
或者,您可以將名稱提供程序注入HotdogContext
並在OnConfiguring( DbContextOptionsBuilder )
方法覆蓋中使用它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.