Home > Enterprise >  Conditional Required attribute based on generic type in c#
Conditional Required attribute based on generic type in c#

Time:05-28

I have a base class "BASE" and another class "RAN" which is a parent of 5 classes "RAN1", "RAN2", ..., "RAN5".

public class RAN {
}
public class RAN1 : RAN {
}
. // RAN2
. // RAN3
. // RAN4
public class RAN5 : RAN {
}

public class BASE<T> where T : RAN {
    [Required]
    public int Myprop {
       get{...}
       set{...}    
    }
}

I want this property "Myprop" to be "required" when T equals RAN2 or RAN4. And this property "Myprop" should be set as "not required" when T equals RAN1, RAN3, RAN5.

How do I achieve this?

CodePudding user response:

We can try to let Myprop property be virtual then we can try to override in RAN2 and RAN4 and add Required attribute for that, other RANs just inherit from RAN

public class RAN {
    public virtual int Myprop { get; set;}
}

public class RAN1 : RAN {
}

public class RAN2 : RAN {
    [Required]
    public override int Myprop { get; set;}
}

public class RAN4 : RAN {
    [Required]
    public override int Myprop { get; set;}
}

CodePudding user response:

You'll have to write a custom validation attribute to make something like this work. This page discusses writing custom attributes. There is also this older page that might have some relevant or useful information.

For example, you could write something like RequiredIfClassHasGenericTypeAttribute by inheriting RequiredAttribute and overriding the protected IsValid(object, ValidationContext) method.

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Somenamespace
{
   public class RequiredIfClassHasGenericTypeAttribute : RequiredAttribute
   {
      public RequiredIfClassHasGenericTypeAttribute(params Type[] requiredGenericTypes)
      {
         RequiredGenericTypes = requiredGenericTypes;
      }

      protected override ValidationResult IsValid(object value, ValidationContext validationContext)
      {
         var instance = validationContext.ObjectInstance;
         var instanceType = instance.GetType();
         if (instanceType.GenericTypeArguments.Intersect(RequiredGenericTypes).Any())
         {
            var result = base.IsValid(value, validationContext);
            return result;
         }
         return ValidationResult.Success;
      }

      private Type[] RequiredGenericTypes { get; }
   }
}

Then you would use it like this...

public class BASE<T> where T : RAN
{
   [RequiredIfClassHasGenericType(typeof(RAN2), typeof(RAN4))]
   public int MyProp { get; set; }
}

It might also be worth mentioning that the RequiredAttribute states in the remarks that:

The RequiredAttribute attribute specifies that when a field on a form is validated, the field must contain a value. A validation exception is raised if the property is null, contains an empty string (""), or contains only white-space characters.

An int will never be null, contain an empty string, or contain only white-space characters so I'm not sure that RequiredAttribute will ever fail for an int.

  • Related