I'm using Configuration Binding in an ASP.NET Core 1.1 solution. Basically, I have some simple code for the binding in my ConfigureServices Startup section that looks like this:
services.AddSingleton(Configuration.GetSection("SettingsSection").Get<SettingsClass>());
The wrinkle is that my class as an int property that is normally bound to an int value in the configuration file, but could be bound instead to the string "disabled". Under the hood, I want the property to get a value of -1 if it is bound to the string "disabled".
It can be more complicated than this, but I'm simplifying for the sake of brevity.
My question is this: How do I provide a custom binder/converter for that overrides the configuration binding for a specific property in SettingsClass so that when doing a string conversion it will convert "disabled" to -1, rather than throwing an exception that "disabled" can't be converted to an Int32?
It appears that since the ConfigurationBinder uses the type's TypeDescriptor to get the converter, the only way for me to do what I'm trying to do is to implement a custom type converter and insert it into the TypeDescriptor for the class I'm converting to (in this case Int32).
So, basically, add this before configuration happens:
TypeDescriptor.AddAttributes(typeof(int), new TypeConverterAttribute(typeof(MyCustomIntConverter)));
Where MyCustomIntConverter looks something like this:
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);
}
}
Seems like overkill, as now "disabled" will always convery to -1 for Int32 everwhere in the application. If anyone knows a less invasive way to do this, please let me know.
I just stumbled upon the same problem recently and came up with slightly different solution.
My idea was to use default binding mechanism. In my case I wanted to get new instance of HashSet
having values stored in proper array format inside my database. I created a class I'm binding my configuration to with one private
property named as in my configuration and one public
property, which uses the private
one to create me an instance of HashSet
. It looks a little like this:
// settings.json
{
option: {
ids:[1,2,3],
}
}
and the class
public class Options
{
public HashSet<int> TrueIds
{
get
{
return RestrictedCategoryIds?.ToHashSet();
}
}
private int[] Ids{ get; set; }
}
Then you can use BindNonPublicProperties
to ensure that binder will fill your private
property.
// Startup.cs
services.Configure<Options>(Configuration, c => c.BindNonPublicProperties = true);
You say that in your case this might be not as simple as converting "disabled" into -1, but maybe my idea will inspire you to solve this one in different way.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With