Custom Validation Attribute

577 Views Asked by At

Currently i try to validate a property by another property of the same class. I got an error which told me the following:

An object reference is required for a non static field, method or property

This kind of error makes absolute sense to me for the following code snippet. But in anyway i try to validate property A (in my example OrderNumber) in reason of the value of property B (in my example Level).

Is there a possibility to do that by using Validation Annotation?

This is currently my code:

    public class A
    {
        /// <summary>
        /// Level 
        /// </summary>
        public string Level { get; set; }

        public B B {get;set;}
    }

    public class B
    {
        /// <summary>
        /// Order Number
        /// </summary>
        [Level(A.Level)]
        public int? OrderNumber { get; set; }
    }



    public class LevelAttribute : ValidationAttribute
    {

        private string Dlevel { get; set; }

        public LevelAttribute(string dlevel)
        {
            this.Dlevel = dlevel;
        }

        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            if (value!=null && (Dlevel.Equals("D1")||Dlevel.Equals("D2")))
            {
                return new ValidationResult("Invalid Error Message");
            }
            return ValidationResult.Success;
        }
    }

Thanks for help.

1

There are 1 best solutions below

4
On

Directly referencing an instance member (method, property, field) is not possible in a custom attribute constructor. But there is an indirect way by defining the property name and resolve the corresponding property value via reflection:

public class A
{
    public A()
    {
        Level = "D3";
    }

    public string Level { get; set; }

    public B B { get; set; }
}

public class B
{
    [Level("MyNamespace.A.Level")]
    public int? OrderNumber { get; set; }
}

public class LevelAttribute : ValidationAttribute
{
    private string PropName { get; set; }

    public LevelAttribute(string prop)
    {
        this.PropName = prop;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        System.Reflection.PropertyInfo property = null;
        object objectinstance = null;

        if (this.PropName.Contains("."))
        {
            string classname = PropName.Substring(0, PropName.LastIndexOf("."));
            string prop = PropName.Substring(PropName.LastIndexOf(".") + 1);
            Type type = Type.GetType(classname);

            objectinstance = System.Activator.CreateInstance(type);
            property = type.GetProperty(prop, System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic);
        }
        else
        {
            objectinstance = validationContext.ObjectInstance;
            property = validationContext.ObjectInstance.GetType().GetProperty(this.PropName, System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic);
        }

        object propertyvalue = property.GetValue(objectinstance, new object[0]);

        if (value != null && propertyvalue != null && (propertyvalue.Equals("D1") || propertyvalue.Equals("D2")))
        {
            return new ValidationResult("Invalid Error Message");
        }
        return ValidationResult.Success;
    }
}