在AspNetCore中构建/实例化静态类的正确方法

时间:2017-07-12 13:06:21

标签: c# json asp.net-mvc asp.net-core

我在ASPNetCore 2017中构建了一个静态AppSettings类的工作示例。我想知道是否有更简单/更好的方法来实现它。我是新人,所以我会喜欢一些专家建议..

我使用MiddleWare组件来实例化包含所有Json appSettings值的Static AppSettings类。我这样做是因为我不希望Controller类必须知道设置它想要查询的DB的连接字符串。我使用SQLClient(不是EF,因为我所有的电话都是存储过程)。

这是我的代码:

appSettings.Json

{    " AppSettings":{     " WarehouseConnectionString":" Data Source = [Removed] \ SQLExpress; Initial Catalog = Warehouse; Integrated Security = True;"   }, }

AppSettings Class

public class AppSettings
{       
    public AppSettings()
    {
        // Set default values of our options.
        WarehouseConnectionString = "WarehouseConnectionString";
    }

    /// <summary>
    ///  Our Warehouse DB Connection string.
    /// </summary>
    public static string WarehouseConnectionString { get; set; }
}

我的MiddleWare课程:

public class ApplicationSettingsService
{
    private readonly RequestDelegate next;

    public ApplicationSettingsService(RequestDelegate next)
    {
        this.next = next;
    }

    public async Task Invoke(HttpContext context, IOptions<AppSettings> appSettings)
    {            
            // Create our static instance of our AppSettings class.                
            AppSettings _settings = appSettings.Value;

            await next(context);            
    }
}

我的Starup.cs课程

public class Startup
{
    public Startup(IHostingEnvironment env)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
            .AddEnvironmentVariables();
        Configuration = builder.Build();
    }

    public IConfigurationRoot Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        //************************************************//
        // Adds services required for using options.
        //************************************************//
        services.AddOptions();

        //**********************************************************************//
        // Register the IConfiguration instance which MyOptions binds against the 
        // AppSettings section of the appsetting.json file only.
        //**********************************************************************//
        services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));         

        // Add framework services.
        services.AddMvc();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        loggerFactory.AddConsole(Configuration.GetSection("Logging"));
        loggerFactory.AddDebug();

        //******************************************************//
        // Add our own custom Application Settings Middleware     //
        //******************************************************//             
        app.UseMiddleware<ApplicationSettingsService>();

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseBrowserLink();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
        }

        app.UseStaticFiles();

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                //template: "{controller=Home}/{action=Index}/{id?}");
                template: "{controller=Box}/{action=Index}/{id?}");
        });
    }
}

使用AppSetting Values的我的数据库连接类。

public static class DBConnection
{
    private static string ConnectionString = AppSettings.WarehouseConnectionString;


    public static SqlConnection GetConnection()
    {
        return new SqlConnection(ConnectionString);
    }
}

当客户端(Controller)调用DB类时,他们不必指定连接字符串,&#34;仓库&#34;已经知道它应该连接到哪个DB ......

   DHRIM5_StoredProcedureDatabaseExample.Data.Warehouse.StoredProcedures sp = new Data.Warehouse.StoredProcedures();

    // GET: Box
    public ActionResult Index()
    {            
        IList<Box> tests = sp.SPGetBoxes().ToList();            
        return View(tests);
    }

感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

通常,您应该避免使用依赖于基础结构的静态类,因为很难对这些类进行单元测试。但是您可以在单例范围内使用非静态类,因此您只能拥有一个实例。在你的情况下 - AppSettings.cs

public class AppSettings
{
    public AppSettings()
    {
        // Set default values of our options.
        WarehouseConnectionString = "default_value_if_needed";
    }

    public string WarehouseConnectionString { get; set; }
}

Startup.cs中获取Configuration的值并将其注册为单身。

public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddMvc();

    var appSettings = Configuration.GetSection("AppSettings").Get<AppSettings>();
    services.AddSingleton(appSettings);
}

然后你可以将这个值注入构造函数

public class DBConnection
{
    private readonly string connectionString;

    public DBConnection(AppSettings settings)
    {
        this.connectionString = settings.WarehouseConnectionString;
    }

    public SqlConnection GetConnection()
    {
        return new SqlConnection(this.connectionString);
    }
}

请注意,在这种情况下,AppSettings仅在启动应用程序上是只读的,因此如果您更改appsettings.json文件,则在不重新启动应用程序的情况下将不会应用这些设置。
现在,您还应该在DbConnection - Startup.cs中将services.AddSingleton<DBConnection>();注册为单身,并通过构造函数参数请求其对象。

public class StoredProcedures
{
    private readonly DBConnection connection;
    public StoredProcedures(DBConnection connection)
    {
        this.connection = connection;
    }
}

当然最好将接口与实现分开并仅使用接口。