Custom .NET ConfigurationSection against multiple values

I am implementing custom .NET ConfigurationSectionand must verify that either of the two conditions is true in the configuration, but I'm not sure how to approach validation against multiple fields.

Basically, the condition is, given the three KVPs (A, B, and C), either A is required, or B and C are required.

Since they are realistic independently of each other, I cannot mark them as required, however, one of two conditions is required for the correct configuration.

I read about writing custom validators on Jon Rista "Decoding Mysteries of the .NET 2.0 Configuration" , but they only confirm the value of a single field.

Should I just embed these three parameters in my own ConfigurationElementand write a validator (or use CallbackValidator) for the property that expands this section? Or is there a better way to test for multiple properties?

+4
source share
2 answers

I ended up dragging these three configuration properties into a custom one ConfigurationElementand using CallbackValidatorfor the property:

public class AlphabetElement : ConfigurationElement
{
    private static ConfigurationPropertyCollection _properties;

    private static ConfigurationProperty _a;
    [ConfigurationProperty("A")]
    public Letter A
    {
        get { return (Letter)base[_a]; }
    }

    private static ConfigurationProperty _b;
    [ConfigurationProperty("B")]
    public Letter B
    {
        get { return (Letter)base[_b]; }
    }

    private static ConfigurationProperty _c;
    [ConfigurationProperty("C")]
    public Letter C
    {
        get { return (Letter)base[_c]; }
    }

    static AlphabetElement()
    {
        // Initialize the ConfigurationProperty settings here...
    }

    public static void Validate(object value)
    {
        AlphabetElement element = value as AlphabetElement;
        if (element == null)
            throw new ArgumentException(
                "The method was called on an invalid object.", "value");

        if (A == null && (B == null || C == null))
            throw new ArgumentException(
                "Big A, little a, bouncing beh... " +
                "The system might have got you but it won't get me.");
    }
}

public class BestBefore : ConfigurationSection
{
    private static ConfigurationPropertyCollection _properties;

    private static ConfigurationProperty _alphabetElement;
    [ConfigurationProperty("alphabet", IsRequired = true)]
    public AlphabetElement Alphabet
    {
        get { return (AlphabetElement)base[_alphabetElement]; }
    }

    static BestBefore()
    {
        _properties = new ConfigurationPropertyCollection();

        _alphabetElement = new ConfigurationProperty(
            "alphabet",
            typeof(AlphabetElement),
            null,
            null,
            new CallbackValidator(
                typeof(AlphabetElement),
                new ValidatorCallback(AlphabetElement.Validate)),
            ConfigurationPropertyOptions.IsRequired);
        _properties.Add(_alphabetElement);
    }
}

And then in the config it will look like this:

<bestBefore ...>
    <alphabet B="B" C="C"/>
</bestBefore>

I will leave it here for posterity.

Crass approves.

+1
source

How about using the methodPostDeserialize ?

protected override void PostDeserialize()
{
    base.PostDeserialize();

    if (A == null && (B == null || C == null))
    {
        throw new ConfigurationErrorsException("...");
    }
}
+2
source

All Articles