如何使用 POCO 对象访问 appsettings.json 文件中的选项数组 (ASP.NET 5)

How to use a POCO object to access an array of options in the appsettings.json file (ASP.NET 5)

我正在使用 ASP.NET 5,我想使用 POCO classes 访问我的 appsettings.json 文件。该文件如下所示:

{
  "Data": {
        "ErpSystemConnection": {
            "ConnectionString": "[myConnectionString]"
        }
  },
    "Logging": {
        "IncludeScopes": false,
        "LogLevel": {
            "Default": "Verbose",
            "System": "Information",
            "Microsoft": "Information"
        }
    },
    "GoogleAnalytics": {
        "Account": [
            {
                "Name": "AccountName",
                "ServiceAccountEmailAddress": "someEmail@someaccount.iam.gserviceaccount.com",
                "KeyFileName": "key1.p12",
                "Password": "notasecret"

            },
            {
                "Name": "AnotherAccount",
                "ServiceAccountEmailAddress": "anotherEmailAccount@someotheraccount.iam.gserviceaccount.com",
                "KeyFileName": "key2.p12",
                "Password": "notasecret"

            }
        ],
        "KeyFilePath": "/googleApis/"
    }
}

'GoogleAnalytics' 键包含我希望能够在集合中以列表或数组形式访问的帐户数组。 我创建了一个 POCO 来表示包含相应的 'Account' 个对象集合的密钥:

public class GoogleAnalytics
{
    public Account[] Account { get; set; } = new Account[1];
    public string KeyFilePath { get; set; }

    public GoogleAnalytics()
    {

    }
}

和 'Account' 对象:

public class Account
{
    private const string _applicationName = @"Storefront Analytics";
    private X509Certificate2 _certificate;
    private ServiceAccountCredential _credential;
    private AnalyticsService _service;

    #region |--Properties--|

    public string Name { get; set; }
    public string Password { get; set; }
    public string ServiceAccountEmailAddress { get; set; }
    public string KeyFileName { get; set; }
    public string KeyFilePath { get; set; }

    public string KeyFileFullPath
    {
        get
        {
            return $"{KeyFilePath}{KeyFileName}";
        }
    }

    public X509Certificate2 Certificate
    {
        get
        {
            if(_certificate == null)
            {
                ConfigureInstance();
            }

            return _certificate;
        }
        set
        {
            _certificate = value;
        }
    }

    public ServiceAccountCredential Credential
    {
        get
        {
            if (_credential == null)
            {
                ConfigureInstance();
            }

            return _credential;
        }
        set
        {
            _credential = value;
        }
    }

    public AnalyticsService Service
    {
        get
        {
            if (_service == null)
            {
                ConfigureInstance();
            }

            return _service;
        }
        set
        {
            _service = value;
        }
    }

    #endregion

    #region |--Constructors--|

    public Account()
    {

    }

    public Account(string password, string keyFileName, 
       string keyFilePath, 
       string serviceAccountEmailAddress, string accountName)
    {
        //TODO: Validate parameters

        Password = password;
        KeyFileName = keyFileName;
        KeyFilePath = keyFilePath;
        ServiceAccountEmailAddress = serviceAccountEmailAddress;
        Name = accountName;
    }

    #endregion

    private void ConfigureInstance()
    {
        Certificate = new X509Certificate2(KeyFileFullPath, Password, X509KeyStorageFlags.Exportable);

        Credential = new ServiceAccountCredential(new ServiceAccountCredential.Initializer(ServiceAccountEmailAddress)
        {
            Scopes = new[] { AnalyticsService.Scope.Analytics }
        });

        Service = new AnalyticsService(new BaseClientService.Initializer()
        {
            HttpClientInitializer = Credential,
            ApplicationName = _applicationName
        });
    }
}

我的控制器:

public class GoogleAnalyticsController : Controller
{
    #region |--Properties--|

    [FromServices]
    private IGoogleAnalyticsRepository _repo { get; set; }

    #endregion

    public GoogleAnalyticsController(IOptions<GoogleAnalytics> options)
    {
        var temp = options.Value;
    }
}

'KeyFilePath' 属性 已在 IOptions 实例中正确设置。

我遇到的问题是帐户数组包含空引用 - none 个帐户正在实例化。我想知道我是否做错了,或者选项模型此时不支持这种行为?

更新以回应 Shaun Luttin 的回答

我实施了 Shaun Luttin 的回答中列出的更改。似乎还有一个问题。无论出于何种原因,在我将 class 简化如下之前,所有 Account 实例的属性都是空的:

public class Account
{

    public string Name { get; set; }
    public string Password { get; set; }
    public string ServiceAccountEmailAddress { get; set; }
    public string KeyFileName { get; set; }
    public string KeyFilePath { get; set; }

}

简答

I wondering if I am doing this wrong, or the Options Model doesn't support this type of behavior at this time?

你做错了一件事。选项模型支持数组。您不需要使用大小为 [1].

的数组来初始化数组 属性
public Account[] Account { get; set; } = new Account[1];     // wrong
public Account[] Account { get; set; }                       // right

演示

这是一个专为您准备的示例,您可以找到 here on GitHub

MyOptions.cs

namespace OptionsExample
{
    public class MyObj
    {
        public string Name { get; set; }
    }

    public class MyOptions
    {
        public string Option1 { get; set; }

        public string[] Option2 { get; set; }

        public MyObj[] MyObj { get; set; }
    }
}

Startup.cs

namespace OptionsExample
{
    using Microsoft.AspNet.Builder;
    using Microsoft.AspNet.Hosting;
    using Microsoft.AspNet.Http;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.OptionsModel;
    using System.Linq;

    public class Startup
    {
        public IConfigurationRoot Config { get; set; }
        public Startup(IHostingEnvironment env)
        {
            Config = new ConfigurationBuilder().AddJsonFile("myoptions.json").Build();
        }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddOptions();
            services.Configure<MyOptions>(Config);
        }

        public void Configure(IApplicationBuilder app, 
            IOptions<MyOptions> opts)
        {
            app.Run(async (context) =>
            {
                var message = string.Join(",", opts.Value.MyObj.Select(a => a.Name));
                await context.Response.WriteAsync(message);
            });
        }
    }
}

myoptions.json

{
    "option1": "option1val",
    "option2": [
        "option2val1",
        "option2val2",
        "option2val3"
    ],
    "MyObj": [
        {
            "Name": "MyObj1"
        },
        {
            "Name": "MyObj2"
        }
    ]
}

project.json 依赖关系

"dependencies": {
    "Microsoft.AspNet.Mvc": "6.0.0-rc1-final",
    "Microsoft.AspNet.Server.Kestrel": "1.0.0-rc1-final",
    "Microsoft.Extensions.Configuration.Json": "1.0.0-rc1-final"
}

输出