lundi 27 mars 2017

C# Validation Pattern - Best practice to validate an Entity over a certain operation

I might be trying to solve this problem in a wrong way and I've also found lots of solutions but none of them answer my particular question.

In short, I want to validate an object (i.e. argument, entity, etc.) over a an operation (i.e. Insert, Update, Select, etc.).

I've created a small code sample here only for 1 class and 2 operations. But in my actual project, there are many more classes like Person and operations.

Person.cs

public class Person
{
   public int Id {get;set;}
   public string Name {get;set;}
   public DateTime Birthdate {get;set;}
   public BeverageSelectionType BeverageSelection {get;set;}
}

BeverageSelectionType.cs

public enum BeverageSelectionType
{ 
    NotSet,
    Juice,
    Beer,
    Water
}

IService.cs

public interface IService
{
   void Update(Person person);
   Person Add(Person person);
}

PersonSevice.cs (To explain it simple, I chose as service, but in reality I use repository pattern and UnitOfWork which I thought writing them here would be long)

public class PersonService : IService
{
    public void Update(Person person)
    {
        if(person.BeverageSelection == BeverageSelectionType.NotSet
           || (person.BeverageSelection == BeverageSelectionType.Beer && person.Birthdate < DateTime.Now.AddYears(-18))
          )
         throw new MyInvalidException("Parameters NOT valid for UPDATE operation");

         //Do update with expected parameters
    }

    public Person Add(Person person)
    {
        if(person.Birthdate <= DateTime.MinValue || person.Birthdate >= DateTime.MaxValue)
         throw new MyInvalidException("Parameters NOT valid for ADD operation");

         //Do add with expected parameters
    } 
}

I need to design such as generic as possible approach for Validation that helps to validate entities against operations. I just don't want to add validation logic in to each service.

Here is another approach that every Entity knows itself when and how it is valid but I though was useful but still believe not good enough:

Person.cs

public class Person
{
       public int Id {get;set;}
       public string Name {get;set;}
       public DateTime Birthdate {get;set;}
       public BeverageSelectionType BeverageSelection {get;set;}

   public bool IsValid(ModelValidationType modelValidationType)
   {
       switch(modelValidationType)
       {
           case ModelValidationType.Update:
               if(person.BeverageSelection == BeverageSelectionType.NotSet
           || (person.BeverageSelection == BeverageSelectionType.Beer && person.Birthdate < DateTime.Now.AddYears(-18))
          )
          return false;

           case ModelValidationType.Add:
            if(person.Birthdate <= DateTime.MinValue || person.Birthdate >= DateTime.MaxValue)
             return false;
       }

     return true;
   }
}

How would you implement the most proper validation approach?

Thanks in advance

Aucun commentaire:

Enregistrer un commentaire