簡體   English   中英

使用擴展方法清理 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM