如何通过绑定读取数组配置部分?

发布于 2025-01-16 23:49:17 字数 1210 浏览 4 评论 0原文

如何使用 Microsoft.Extensions.Configuration 和绑定读取配置值数组?

例如,给定以下 XML 配置:

<root>
    <eventConfiguration>
        <event name="0" source="" type="" target="" />
        <event name="1" source="" type="" target="" />
        <event name="2" source="" type="" target="" />
    </eventConfiguration>
</root>

和以下类:

public class Configuration
{
    public EventConfiguration EventConfiguration {get; set;}
}

public class EventConfiguration
{
    public List<Event> Events {get; set;}
}

public class Event
{
    public string Name {get; set;}
    public string Source {get; set;}
    public string Type {get; set;}
    public string Target {get; set;}
}

当我尝试获取 Configuration 的实例时,事件列表为 null:

IConfigurationBuilder builder = new ConfigurationBuilder();
builder.AddXmlFile("default.xml");
var root = builder.Build();
    
// with binding
var configuration = root.Get<Configuration>();
var events = configuration.EventConfiguration.Events; // null

// without binding
var eventSource = root.GetValue("eventConfiguration:event:0:source", default(string)); // not null

How can I read an array of configuration values using Microsoft.Extensions.Configuration with binding?

For example, given the following XML configuration:

<root>
    <eventConfiguration>
        <event name="0" source="" type="" target="" />
        <event name="1" source="" type="" target="" />
        <event name="2" source="" type="" target="" />
    </eventConfiguration>
</root>

And the following classes:

public class Configuration
{
    public EventConfiguration EventConfiguration {get; set;}
}

public class EventConfiguration
{
    public List<Event> Events {get; set;}
}

public class Event
{
    public string Name {get; set;}
    public string Source {get; set;}
    public string Type {get; set;}
    public string Target {get; set;}
}

When I try to get an instance of Configuration the Event-List is null:

IConfigurationBuilder builder = new ConfigurationBuilder();
builder.AddXmlFile("default.xml");
var root = builder.Build();
    
// with binding
var configuration = root.Get<Configuration>();
var events = configuration.EventConfiguration.Events; // null

// without binding
var eventSource = root.GetValue("eventConfiguration:event:0:source", default(string)); // not null

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

哭了丶谁疼 2025-01-23 23:49:17

解决方案是将 ConfigurationKeyNameAttribute 添加到 Events 属性,因为 XML 元素的名称是 event 而不是 events

public class EventConfiguration
{
    [ConfigurationKeyName(nameof(Event))]
    public List<Event> Events { get; set; }
}

更新#1:

这是我的有效代码。

ConsoleApp1.csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="6.0.0" />
    <PackageReference Include="Microsoft.Extensions.Configuration.Xml" Version="6.0.0" />
  </ItemGroup>

  <ItemGroup>
    <None Update="default.xml">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </None>
  </ItemGroup>

</Project>

default.xml

<?xml version="1.0" encoding="utf-8" ?>
<root>
  <eventConfiguration>
    <event name="0" source="" type="" target="" />
    <event name="1" source="" type="" target="" />
    <event name="2" source="" type="" target="" />
  </eventConfiguration>
</root>

Program.cs

using Microsoft.Extensions.Configuration;

using System;
using System.Collections.Generic;

namespace ConsoleApp1
{
    internal class Program
    {
        static void Main(string[] args)
        {
            IConfigurationBuilder builder = new ConfigurationBuilder();
            builder.AddXmlFile("default.xml");
            var configurationRoot = builder.Build();

            // with binding
            var configuration = configurationRoot.Get<Configuration>();
            var events = configuration.EventConfiguration.Events;

            Console.WriteLine($"events.Count = [{events?.Count}]");

            for (int i = 0; i < (events?.Count ?? 0); i++)
            {
                Console.WriteLine(events[i]);
            }

            // without binding
            var eventSource = configurationRoot.GetValue("eventConfiguration:event:0:source", default(string));
        }
    }

    public class Configuration
    {
        public EventConfiguration EventConfiguration { get; set; }
    }

    public class EventConfiguration
    {
        [ConfigurationKeyName(nameof(Event))]
        public List<Event> Events { get; set; }
    }

    public class Event
    {
        public string Name { get; set; }
        public string Source { get; set; }
        public string Type { get; set; }
        public string Target { get; set; }

        public override string ToString()
        {
            return $"Event: Name=[{Name}]";
        }
    }
}

输出为:

events.Count = [3]
Event: Name=[0]
Event: Name=[1]
Event: Name=[2]

P:\Projects\ConsoleApp1\ConsoleApp1\bin\Debug\netcoreapp3.1\ConsoleApp1.exe (process 15136) exited with code 0.
Press any key to close this window . . .

The solution is to add ConfigurationKeyNameAttribute to the Events property as your XML element's name is event not events.

public class EventConfiguration
{
    [ConfigurationKeyName(nameof(Event))]
    public List<Event> Events { get; set; }
}

Update #1:

This is my code that works.

ConsoleApp1.csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="6.0.0" />
    <PackageReference Include="Microsoft.Extensions.Configuration.Xml" Version="6.0.0" />
  </ItemGroup>

  <ItemGroup>
    <None Update="default.xml">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </None>
  </ItemGroup>

</Project>

default.xml

<?xml version="1.0" encoding="utf-8" ?>
<root>
  <eventConfiguration>
    <event name="0" source="" type="" target="" />
    <event name="1" source="" type="" target="" />
    <event name="2" source="" type="" target="" />
  </eventConfiguration>
</root>

Program.cs

using Microsoft.Extensions.Configuration;

using System;
using System.Collections.Generic;

namespace ConsoleApp1
{
    internal class Program
    {
        static void Main(string[] args)
        {
            IConfigurationBuilder builder = new ConfigurationBuilder();
            builder.AddXmlFile("default.xml");
            var configurationRoot = builder.Build();

            // with binding
            var configuration = configurationRoot.Get<Configuration>();
            var events = configuration.EventConfiguration.Events;

            Console.WriteLine(
quot;events.Count = [{events?.Count}]");

            for (int i = 0; i < (events?.Count ?? 0); i++)
            {
                Console.WriteLine(events[i]);
            }

            // without binding
            var eventSource = configurationRoot.GetValue("eventConfiguration:event:0:source", default(string));
        }
    }

    public class Configuration
    {
        public EventConfiguration EventConfiguration { get; set; }
    }

    public class EventConfiguration
    {
        [ConfigurationKeyName(nameof(Event))]
        public List<Event> Events { get; set; }
    }

    public class Event
    {
        public string Name { get; set; }
        public string Source { get; set; }
        public string Type { get; set; }
        public string Target { get; set; }

        public override string ToString()
        {
            return 
quot;Event: Name=[{Name}]";
        }
    }
}

The output is:

events.Count = [3]
Event: Name=[0]
Event: Name=[1]
Event: Name=[2]

P:\Projects\ConsoleApp1\ConsoleApp1\bin\Debug\netcoreapp3.1\ConsoleApp1.exe (process 15136) exited with code 0.
Press any key to close this window . . .
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文