如何将POCO类传递给.NET Core配置

时间:2018-03-20 11:13:42

标签: asp.net-core .net-core

我正在开发.NET Core应用程序的集成测试,并希望使用一些测试配置。我的配置是POCO类,它通过appsettings.json配置,然后通过IOptions<T>使用。在我的测试中,我想使用该类的实例。

以下是代码:

 var mySettings = GetTestSettings(); // factory method returning POCO class 
 var configurationBuilder = new ConfigurationBuilder();

 // I am looking for something like 
 configurationBuilder.AddInMemoryObject("Settings", mySettings);

 // does not work, result is just string 
 configurationBuilder.AddInMemoryCollection("Settings",
        JsonConvert.SerializeObject(mySettings)); 

// requires filename
configurationBuilder.AddJsonFile("filename.json");

将POCO提供给配置的最简单方法是什么?

2 个答案:

答案 0 :(得分:9)

AddInMemoryCollection采用KeyValuePair的集合,其中键设置键,值为其值。来自问题的这个电话

configurationBuilder.AddInMemoryCollection("Settings", JsonConvert.SerializeObject(mySettings));

实际上将“设置”作为键和整个JSON作为一个设置值传递,预计不起作用。

但总体方法是正确的,您应该使用AddInMemoryCollection分机号码。在传递给此调用的集合中,设置键是配置中的完整路径,由冒号分隔。假设您有以下设置POCO:

public class SomeSettings
{
    public string SomeKey1 { get; set; }
    public int SomeKey2 { get; set; }
}

它从以下JSON加载

{
    "SomeSettings": {
        "SomeKey1": "SomeData",
        "SomeKey2": 123
    } 
}

密钥为SomeSettings:SomeKey1SomeSettings:SomeKey2

然后,您可以通过以下AddInMemoryCollection调用添加此类配置:

configurationBuilder.AddInMemoryCollection(new Dictionary<string, string>
{
    { "SomeSettings:SomeKey1", "SomeData" },
    { "SomeSettings:SomeKey2", 123 },
});

现在,如果您想通过一次调用添加设置POCO,您可以编写简单的扩展方法,该方法将使用反射枚举设置类属性并返回属性名称和值的键值对的集合。

以下是一个示例:

public static class ObjectExtensions
{
    public static IEnumerable<KeyValuePair<string, string>> ToKeyValuePairs(this Object settings, string settingsRoot)
    {
        foreach (var property in settings.GetType().GetProperties())
        {
            yield return new KeyValuePair<string, string>($"{settingsRoot}:{property.Name}", property.GetValue(settings).ToString());
        }
    }
}

public static class ConfigurationBuilderExtensions
{
    public static void AddInMemoryObject(this ConfigurationBuilder configurationBuilder, object settings, string settingsRoot)
    {
        configurationBuilder.AddInMemoryCollection(settings.ToKeyValuePairs(settingsRoot));
    }
}

在测试中:

var configurationBuilder = new ConfigurationBuilder();
var mySettings = GetTestSettings();
configurationBuilder.AddInMemoryObject(mySettings, "Settings");

这种简单的ObjectExtensions.ToKeyValuePairs扩展方法适用于上面的SomeSettings之类的普通POCO。但是,如果某些属性也是像这样的对象,它将无法工作:

public class InnerSettings
{
    public string SomeKey { get; set; }
}

public class OuterSettings
{
    public InnerSettings InnerSettings { get; set; }
}

但是我相信你有了一个想法,如果需要可以进行必要的调整。

答案 1 :(得分:2)

我最终得到了以下内容:

configurationBuilder.AddInMemoryCollection(ToDictionary(GetTestSettings()));

private static IEnumerable<KeyValuePair<string, string>> ToDictionary(object o) => 
    AddPropsToDic(JObject.FromObject(o), new Dictionary<string, string>(), "Settings");

private static Dictionary<string, string> AddPropsToDic(JObject jo, Dictionary<string, string> dic, string prefix)
{
    jo.Properties()
        .Aggregate(dic, (d, jt) =>
        {
            var value = jt.Value;
            var key = $"{prefix}:{jt.Name}";

            if (value.HasValues)
                return AddPropsToDic((JObject) jt.Value, dic, key);

            dic.Add(key, value.ToString());
            return dic;
        });
    return dic;
}
相关问题