views:

91

answers:

1

Hi there,

I again need help by you, this time I struggle with covariance, contravariance, delegates and an simple idea blowing up...

I want to implement an attribute for our businessobject-properties that takes a delegate and the needed parameters for that one, so that I can work with reflection, read out the attribute and perform a validation on the property value.

The reason behind this is, we are using Windows.Forms with DataBinding and need to set the DataBinding update method to OnPropertyChanged, to get a properly working refresh on the GUI. We do need however a way to react in the validating-events of the controls to validate the property correctly, to see if the user can actually e.g. save the object. But the Validating-Event of the control occurs only after writing the value to the property. Having a validation in the setter of the property would cause a crash and we could not provide the user exact information what is wrong unless we implement the validation a second time (or extract it to a method called from the setter).

To keep this most elegant and clean, I thought one of the following would be nice to have:

[PropertyValidator(ValidationHelper.ValidateString, new StringValidatorArgs(true, 3, 15))]

That way I could iterate via reflection over all properties, perform all validations we want them to and set a PropertyValidator-Attribute for with the correct Method. But I played with the idea a bit and do not get this anyway to work, here is what I have, might be you have an idea about how to achive this.

public delegate bool Validator(object validatee, ValidatorArgs v);

public class ValidatorArgs
{
}

public class StringValidatorArgs : ValidatorArgs
{
    public StringValidatorArgs(bool nullCheck, int minLength, int maxLength)
    {
        this.NullCheck = nullCheck;
        this.MinLength = minLength;
        this.MaxLength = maxLength;
    }

    public bool NullCheck { get; set; }
    public int MinLength { get; set; }
    public int MaxLength { get; set; }
}

public class MyClass
{
    [PropertyValidator(ValidationHelper.ValidateString, new StringValidatorArgs(true, 3, 15))]
    public string MyString { get; set; }
}

public static class ValidationHelper
{
    public static bool ValidateString(object validatee, StringValidatorArgs v)
    {
        return true;
    }
}

[AttributeUsage(AttributeTargets.Property, Inherited = true, AllowMultiple = true)]
public class PropertyValidatorAttribute
    : Attribute
{
    #region Constructor

    private PropertyValidatorAttribute()
    {
    }

    public PropertyValidatorAttribute(Validator validator, ValidatorArgs args)
    {
        this.Validator = validator;
        this.Args = args;
    }

    #endregion

    #region Properties

    public Validator Validator
    {
        get;
        private set;
    }

    public ValidatorArgs Args
    {
        get;
        private set;
    }

    #endregion
}

Any hints welcome...

+2  A: 

What about implementing IDataErrorInfo to provide validation information from your object, instead of (I'm assuming) throwing an exception from the setter on bad data? Most Windows Forms controls are IDataErrorInfo savvy, and will provide corresponding UI validation information on a per-property or per-object basis.

rh