属性的自定义配置绑定器

Posted

技术标签:

【中文标题】属性的自定义配置绑定器【英文标题】:Custom Configuration Binder for Property 【发布时间】:2017-06-19 19:31:29 【问题描述】:

我在 ASP.NET Core 1.1 解决方案中使用配置绑定。基本上,我的 ConfigureServices 启动部分中有一些简单的绑定代码,如下所示:

services.AddSingleton(Configuration.GetSection("SettingsSection").Get<SettingsClass>());

问题在于,我的类作为 int 属性通常绑定到配置文件中的 int 值,但可以改为绑定到字符串“disabled”。在后台,如果属性绑定到字符串“disabled”,我希望该属性的值为 -1。

它可能比这更复杂,但为了简洁起见,我正在简化。

我的问题是:我如何提供一个自定义绑定器/转换器来覆盖 SettingsClass 中特定属性的配置绑定,以便在进行字符串转换时它将“禁用”转换为 -1,而不是抛出一个“禁用”的异常不能转换为 Int32?

【问题讨论】:

【参考方案1】:

看来,由于 ConfigurationBinder 使用类型的 TypeDescriptor 来获取转换器,所以我要做的唯一方法是实现自定义类型转换器并将其插入到我的类的 TypeDescriptor 中m 转换为(在本例中为 Int32)。

所以,基本上,在配置发生之前添加这个:

TypeDescriptor.AddAttributes(typeof(int), new TypeConverterAttribute(typeof(MyCustomIntConverter)));

MyCustomIntConverter 看起来像这样:

public class MyCustomIntConverter  : Int32Converter

    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    
        if (value != null && value is string)
        
            string stringValue = value as string;
            if(stringValue == "disabled")
            
                return -1;
            
        
        return base.ConvertFrom(context, culture, value);
    

似乎有点矫枉过正,因为现在“禁用”将始终转换为 -1 用于应用程序中的任何地方的 Int32。如果有人知道一种侵入性较小的方法,请告诉我。

【讨论】:

【参考方案2】:

我最近偶然发现了同样的问题,并提出了略有不同的解决方案。

我的想法是使用默认绑定机制。就我而言,我想获得HashSet 的新实例,其值存储在我的数据库中的proper array format 中。我创建了一个类,我将我的配置绑定到一个private 在我的配置中命名的属性和一个public 属性,它使用private 为我创建一个HashSet 的实例。看起来有点像这样:

// settings.json

    option: 
        ids:[1,2,3],
    

还有class

public class Options

    public HashSet<int> TrueIds
    
        get
        
            return RestrictedCategoryIds?.ToHashSet();
        
    

    private int[] Ids get; set; 

然后您可以使用BindNonPublicProperties 来确保活页夹将填充您的private 属性。

// Startup.cs
services.Configure<Options>(Configuration, c => c.BindNonPublicProperties = true);

您说在您的情况下,这可能不像将“禁用”转换为-1那么简单,但也许我的想法会激发您以不同的方式解决这个问题。

【讨论】:

以上是关于属性的自定义配置绑定器的主要内容,如果未能解决你的问题,请参考以下文章

自定义模型绑定器未针对 ASP.NET Core 2 中的单个属性触发

使用自定义模型绑定器的递归模型绑定

.NET Core 自定义模型绑定器调用默认模型绑定器

Web API 验证不使用自定义模型绑定器触发

P23 自定义Model绑定器

没有绑定器的 RxSwift 自定义数据类型转换