是否可以将配置绑定到.Net Core中的无状态/只读模型

kus*_*men 5 .net c# asp.net-core

所以通常我们会有一些模型

public class ConnectionStrings
{
    public string Sql { get; set; }
    public string NoSql { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

那么我们有appsettings.json如下内容:

"ConnectionStrings": {
    "Sql": "some connection string",
    "NoSql": "some other connection string"
}
Run Code Online (Sandbox Code Playgroud)

然后我将模型绑定如下:

services.Configure<ConnectionStrings>(
            options => Configuration.GetSection("ConnectionStrings").Bind(options));
Run Code Online (Sandbox Code Playgroud)

一切正常,但是我的模型可变性并不重要,因为它保存着重要的信息,而且所有配置都是静态信息之后,因此一旦读取,我的模型应该保持原样。还有其他更安全的方法吗?

Geo*_*gan 7

作为版本2.1+的替代方法,您现在可以通过指定与非公共属性绑定BinderOptions

services.Configure<ConnectionStrings>(options => 
        Configuration.GetSection("ConnectionStrings")
                .Bind(options, c => c.BindNonPublicProperties = true));
Run Code Online (Sandbox Code Playgroud)

或只是获得它们:

var connectionStrings = Configuration.GetSection("ConnectionStrings")
        .Get<ConnectionStrings>(c => c.BindNonPublicProperties = true);
Run Code Online (Sandbox Code Playgroud)

  • 这是否要求属性类似于“public string Sql { get; 私人套装;}` 而不是只是 `public string Sql { get; }` ? [文档](https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.configuration.binderoptions.bindnonpublicproperties?view=dotnet-plat-ext-5.0) 指出“如果为 true,则绑定器将尝试设置所有非只读属性。” 正如OP所描述的那样,这似乎排除了只读属性。 (2认同)

Set*_*Set 5

像这样的代码使用了ConfigurationBinder需要公共属性的底层。从BindProperty 方法

// We don't support set only, non public, or indexer properties
if (property.GetMethod == null ||
   !property.GetMethod.IsPublic ||
   property.GetMethod.GetParameters().Length > 0)
{
   return;
}
Run Code Online (Sandbox Code Playgroud)

作为一种解决方法,我可能建议您手动填充您的课程。以以下为例:

public class ConnectionStrings
{
    public ConnectionStrings(string sql, string noSql)
    {
        Sql = sql;
        NoSql = noSql;
    }

    public string Sql { get; private set; }
    public string NoSql { get; private set; }
}
Run Code Online (Sandbox Code Playgroud)

然后在ConfigureServices方法中:

var sqlValue = Configuration.GetValue<string>("ConnectionStrings:Sql", string.Empty);
var noSqlValue = Configuration.GetValue<string>("ConnectionStringsApp:NoSql", string.Empty);

services.Configure<ConnectionStrings>(
           options => new ConnectionStrings(sqlValue, noSqlValue));
Run Code Online (Sandbox Code Playgroud)