【问题标题】:Is there a way to override collection that has been initialized by auto-property initialize syntax with values from configuration in .Net Core?有没有办法用 .Net Core 中的配置值覆盖已通过自动属性初始化语法初始化的集合?
【发布时间】:2019-12-10 09:06:56
【问题描述】:

我有一个保存我的配置值的类:

public class DummyConfiguration
    {
        public List<DummyConfigurationObject> DummyConfigurationCollection { get; set; } =
            new List<DummyConfigurationObject>
            {
                new DummyConfigurationObject
                {
                    DummyField = "DummyConfigurationObject1",
                },
                new DummyConfigurationObject
                {
                    DummyField = "DummyConfigurationObject2",
                },
            };
    }

我使用自动初始化的属性来提供一些适合我的合理默认值。

这是我的 appsettings.yaml:

DummyConfigurationCollection:
    - DummyField: DummyConfigurationObject3
    - DummyField: DummyConfigurationObject4
    - DummyField: DummyConfigurationObject5

当我调用 configuration.Get().DummyConfigurationCollection.Count 时,我会得到 5 个原因集合已初始化,默认绑定器仅使用 Add 方法添加其他条目。但是,如果我的配置文件中有一些与此属性相对应的值,我想要的是完全替换我的默认值。

这可以使用默认配置绑定吗?

【问题讨论】:

    标签: c# .net-core .net-standard .net-core-configuration


    【解决方案1】:

    是的,您可以像这样配置您的应用程序:

    services.Configure<DummyConfiguration>(options => {
     DummyConfiguration.DummyConfigurationCollection.Clear();
     return Configuration.GetSection("DummyConfiguration").Bind(options)
    });
    

    这是 Configure 的重载,允许您配置绑定的完成方式。在这种情况下,我们会在绑定实际配置值之前清除结果选项实例上的所有条目。

    稍后您可以在任何其他带有IOptions&lt;DummyConfiguration&gt; 的服务上使用它,它只会显示配置的值,而不是默认值。

    这是我在 github 上的一个测试库:https://github.com/bison92/IConfigurationCollectionBinding/tree/c29534f41cf07ea22107493d45999fe546462406

    编辑

    当您想使用Configuration.Get() 时,除了指定您是否要尝试绑定私有属性或不尝试绑定 AFAIK 之外,无法修改其行为。

    因此,您可能想尝试实现您的自定义 ICollection,例如使用 2 个列表(默认值、当前值)支持它并覆盖其方法,以便它响应当前值或默认值,但始终修改当前值。

    public class DefaultBackedCollection<T> : ICollection<T>
    {
        private readonly IList<T> defaults;
        private readonly IList<T> currents = new List<T>();
        public DefaultBackedCollection(List<T> defaultElements)
        {
            defaults = defaultElements ?? new List<T>();
        }
        public int Count => currents.Any() ? currents.Count : defaults.Count;
    
        public bool IsReadOnly => false;
    
        public void Add(T item)
        {
            currents.Add(item);
        }
    
        public void Clear()
        {
            currents.Clear();
        }
    
        public bool Contains(T item)
        {
            return currents.Any() ? currents.Contains(item) : defaults.Contains(item);
        }
    
        public void CopyTo(T[] array, int arrayIndex)
        {
            if (currents.Any())
            {
                currents.CopyTo(array, arrayIndex);
            }
            else 
            {
                defaults.CopyTo(array, arrayIndex); 
            }
        }
    
        public IEnumerator<T> GetEnumerator()
        {
            return currents.Any() ? currents.GetEnumerator() : defaults.GetEnumerator();
        }
    
        public bool Remove(T item) => currents.Remove(item);
    
        IEnumerator IEnumerable.GetEnumerator()
        {
            return currents.Any() ? currents.GetEnumerator() : defaults.GetEnumerator();
        }
    }
    

    查看更新后的工作示例:https://github.com/bison92/IConfigurationCollectionBinding

    【讨论】:

    • 对不起,但这不是我需要的。从问题中可以看出,我正在使用配置实例来访问我的配置对象:configuration.Get().DummyConfigurationCollection。 IOptions 和 DI 不是我的选择。无论如何,谢谢。
    • 你在开玩笑吗?你在做没有 DI 的 aspnetcore?
    • 我正在使用 .netstandard,但这不是问题 :) 无论如何,即使配置文件中没有相应的值,您的解决方案也会删除所有默认值,这使得默认值有点毫无意义 :)
    • 好吧 4 个“netcore”标签让我觉得这是 netcore 而不是 netstandard。在任何情况下,您都不想不使用 DI,没有它,即使不是不可能,单元测试也会很痛苦。
    • 自定义收藏的好主意。我会接受答案,因为考虑到所有约束,它看起来已经尽可能接近所需的实现了。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-03-05
    • 2017-02-14
    • 2011-05-30
    • 1970-01-01
    • 2011-02-16
    • 1970-01-01
    • 2021-02-26
    相关资源
    最近更新 更多