0

I have a method with a ValidationContext as parameter.

Here is an exemple of what I would like to achieve.

The objective is to check if there are duplicates in the DbSet<Vehicule> if it'a Vehicule, on DbSet<Color> if it's a Color, etc...

protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
    MultiRetouchesEntities db = new MultiRetouchesEntities();
    Type testType = validationContext.ObjectInstance.GetType();
    switch (testType.Name)
    {
        case "Vehicule":
            Vehicule vehicule = (Vehicule)validationContext.ObjectInstance;

            bool validateName = db.Vehicule.Any(x => x.Name =(string)value);
            if (validateName == true)
            {
                return new ValidationResult("This vehicule already exists", new string[] { "Name" });
            }
        break;
        case "Color":
            Color vehicule = (Color)validationContext.ObjectInstance;
            //Do something with db.Color, for exemple
            db.Color.Add(Color);
            break;
    }
    return ValidationResult.Success;
}

Here I'm using a switch statement, which is working, but is there a cleanest solution?

Manta
  • 490
  • 5
  • 18

2 Answers2

1

you can consider to use Polymorph instead If or switch case.

Create a base class ModelValidBase for Vehicule and Color two types.

Pass parameters in constructor method, which you will use in future.

  1. ValidationContext v validtionContext.
  2. object p vaild parameter.

there is a abstract ValidationResult Dosomthing() method fof subclass to implementate

public abstract class ModelValidBase {
    protected ValidationContext _validContext;
    protected object parameterValue;
    public ModelValidBase(ValidationContext v, object p)
    {
        _validContext = v;
        parameterValue = p;
    }
    public abstract ValidationResult Dosomthing();
}

VehiculeContext implementation ModelValidBase class and override ValidationResult Dosomthing,make your logic in this class

public class VehiculeContext : ModelValidBase
{
    public VehiculeContext(ValidationContext v, object p) : base(v, p)
    {
    }

    public override ValidationResult Dosomthing()
    {
        MultiRetouchesEntities db = new MultiRetouchesEntities();
        Vehicule vehicule = (Vehicule)(_validContext.ObjectInstance) ;

        bool validateName = db.Vehicule.Any(x => x.Name == (string)parameterValue);
        if (validateName == true)
        {
            return new ValidationResult("This vehicule already exists", new string[] { "Name" });
        }

        return ValidationResult.Success;
    }
}

ColorContext implementation ModelValidBase class and override ValidationResult Dosomthing,make your logic in this class

public class ColorContext : ModelValidBase
{
    public ColorContext(ValidationContext v, object p) : base(v, p)
    {
    }

    public override ValidationResult Dosomthing()
    {
        Color vehicule = (Color)_validContext;
        //Do something with db.Color, for exemple
        db.Color.Add(Color);

        return ValidationResult.Success;
    }
}

In the final step create dictionary<string, ModelValidBase> and register VehiculeContext and ColorContext in the dictionary.

you can get the instance by the string name that can instead if else or switch case control flow

public class MyCustomerAttribute : ValidationAttribute
{
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        Dictionary<string, ModelValidBase> _registerTable = new Dictionary<string, ModelValidBase>();
        _registerTable.Add("Vehicule", new VehiculeContext(validationContext,value));
        _registerTable.Add("Color", new ColorContext(validationContext, value));
        Type testType = validationContext.ObjectInstance.GetType();

        ModelValidBase excuteValid;

        if (!_registerTable.TryGetValue(testType.Name, out excuteValid))
        {
            //return a result when you didn't get context from the register table.
        }

        return excuteValid.Dosomthing();
    }
}
Manta
  • 490
  • 5
  • 18
D-Shih
  • 44,943
  • 6
  • 31
  • 51
  • Thanks for your job. I've only make small corrections in order to compile and it's working fine. But even it's a cleanest solution, I'm not sure to implement it because I have to code one derived class of `ModelValidBase` per entity. – Manta Sep 21 '18 at 10:17
  • 1
    Polymorphy usually uses for instead control flow like `if ... else`, let the code make more sence, it's OOP core. @Manta – D-Shih Sep 21 '18 at 10:41
-1

For those who are interested in, here is how I solved.

The main point is the use of System.Linq.Dynamic.

protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
    MultiRetouchesEntities db = new MultiRetouchesEntities();

    Type entityType = validationContext.ObjectInstance.GetType();
    string propertyName= validationContext.ObjectType.GetProperty(validationContext.MemberName).Name.ToLower();

    int nbOfEntities = db.Set(entityType).Where(propertyName + "=@0",((string)value).ToLower()).Count();

    return nbOfEntities == 0 ? ValidationResult.Success : new ValidationResult("Le nom choisi existe déjà !");
}
Manta
  • 490
  • 5
  • 18