Avoid repeating property name 3 times using ConfigurationPropertyAttribute
-
05-06-2021 - |
Question
Repeating the ConfigurationPropertyAttribute
name three times in the code really bothers me.
It so easy to miss a misspelling or copy/paste a property and forget to update one instance of the name.
Declaring a constant only solves one of these problems. Is there a better way?
I tried reflection, but enumerating the attributes seemed much more trouble, and uglier.
[ConfigurationProperty("port", DefaultValue = (int)0, IsRequired = false)]
[IntegerValidator(MinValue = 0, MaxValue = 8080, ExcludeRange = false)]
public int Port
{
get
{
return (int)this["port"];
}
set
{
this["port"] = value;
}
}
I know DRY is just a principle and often, in the real-world, principles must give way to pragmatism. But I'm sure someone has cleaner way?
Solution
You can use a non-declarative approach for configuration elements if you want. Examples can be found all over the internet - particularly at Unraveling the Mysteries of .NET 2.0 Configuration where the examples show both methods simultaneously.
class MyConfigurationElement : ConfigurationElement
{
private static ConfigurationPropertyCollection _properties = new ConfigurationPropertyCollection();
private static ConfigurationProperty _portProperty = new COnfigurationProperty("port", ..... ); // Will leave as example for you to add validator etc.
static MyConfigurationElement()
{
_properties.Add(_portProperty);
}
protected override ConfigurationPropertyCollection Properties
{
get { return _properties; }
}
public int Port
{
get
{
return (int)this[_portProperty];
}
set
{
this[_portProperty] = value;
}
}
}
OTHER TIPS
Why does using a constant not solve all three problems?
Example:
class MyConfigurationElement : ConfigurationElement
{
// Use public, private or internal, as you see fit.
private const string PortName = "port";
// Add something like this, if you also want to access the string value
// and don't want to recompile dependend assemblies when changing the
// string 'port' to something else.
// public static readonly PortNameProperty = PortName;
[ConfigurationProperty(PortName, DefaultValue = (int)0, IsRequired = false)]
[IntegerValidator(MinValue = 0, MaxValue = 8080, ExcludeRange = false)]
public int Port
{
get
{
return (int)this[PortName];
}
set
{
this[PortName] = value;
}
}
}
Side Note: If you might also consider using the Configuration Section Designer. Frankly, I have only tested it a couple of years ago and never used it since then, but maybe it also solves your concerns about DRY.