首页 > 解决方案 > 将配置读入基类对象集合作为子类对象

问题描述

我有 .Net 核心应用程序,它使用 appsetigs.json 文件来保存配置。我需要将配置部分加载到集合中,而不需要遍历它们。我知道我可以使用 Bind() 方法将集合绑定到相同类型的集合中。但是在这里我试图在集合中获取子类类型的对象,而不是基类类型。

"Sections": [
{
  "Name": "Section 1",
  "Type":"type1"

},
{
  "Name": "Section 2",
  "Type":"type2"

},
{
  "Name": "Section 3",
  "Type":"type1"

},
{
  "Name": "Section 4",
  "Type":"type1"

},
{
  "Name": "Section 5",
  "Type":"type2"

}]

我正在使用下面的代码来读取配置文件。

var configBuilder = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("appsettings.json");

        var Configuration = configBuilder.Build();

我知道我可以使用 Configuration.Bind()

课程是

    Public abstract class BaseSection:ISection
    {
    public string Name;
    ..
    }


Public class Type1:BaseSection
{
public string Name;
..
}

Public class Type2:BaseSection
{
public string Name;
..
}

我需要将 appsettings.json 文件中的配置读取到 List 中,以便配置文件中具有“type=type1”的 for 条目将在集合 Type1 对象中具有类型,而“type=type2”将在集合 Type2 中具有类型对象。

所以我从上面的配置条目中收集的应该有

[
    Object Of Type1
    Object Of Type2
    Object Of Type1
    Object Of Type1
    Object Of Type2
]

我不想读取一次数据然后键入强制转换。

请分享观点和意见。提前致谢。

标签: c#design-patternsdependency-injection.net-coreconfiguration

解决方案


您可以使用带有绑定的中间列表,但您必须做一些工作来实例化正确的类型。你可以这样做:

 namespace CoreApp1
 {
    public class ConfigSectionItem: BaseSection
    {
        public string Type { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var configBuilder = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("appsettings.json");

            var configuration = configBuilder.Build();
            var confList = new List<ConfigSectionItem>();

            configuration.GetSection("Sections").Bind(confList);

            foreach (var confItem in confList)
            {
                var typeToBuild = Type.GetType($"CoreApp1.{confItem.Type}"); // Remember to do some checks with typeToBuild (not null, ...)
                var newInstance = (BaseSection)Activator.CreateInstance(typeToBuild);

                newInstance.Name = confItem.Name; // Use automapper or reflexion

                // do what you want here with your newInstance
                Console.WriteLine(newInstance.GetType().FullName + " " + newInstance.Name);
            }
        }
    }

    public abstract class BaseSection
    {
        public string Name;
    }

    public class Type1 : BaseSection
    {
    }

    public class Type2 : BaseSection
    {
    }
 }

请务必使用 Microsoft.Extensions.Configuration.Binder 并且请注意在 .json 中区分大小写或做一些工作以大写:

  "Type": "Type1"
  "Type": "Type2"

推荐阅读