I am using Entity Framework v4. I am trying to implement some logic to check my objects before they are saved by overriding the SaveChanges method. I am also POCO for my entities.
I get a list of changed and new objects by following these steps.
var entities = (ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Modified)) .Select(ose => ose.Entity).OfType<IValidatable>(); foreach(var entity in entities) { var validator = validatorProvider.GetValidator(entity); var errors = validator.Validate(entity); if (errors.Count() > 0) { throw new Exception("A validation error"); } }
And here is the code for my GetValidator method:
private static IValidator<TObject> GetValidator<TObject>(TObject obj) where TObject : IValidatable { var objType = obj.GetType(); var validatorType = Type.GetType("SmsPortal.Validation." + objType.Name + "Validator"); var varValidator = Activator.CreateInstance(validatorType); return (IValidator<TObject>)varValidator; }
The problem is that I get rejected saying:
Unable to cast object of type 'Blah.Validation.ConcreteValidator' to type 'Blah.Validation.IValidator`1[Blah.Validation.IValidatable]'
The only thing I can do to get rid of this error is to first direct the object to the desired type, but I do not want everything to be thrown.
Here is my interface for IValidator
public interface IValidator<TEntity> where TEntity : IValidatable { IEnumerable<ValidationError> Validate(TEntity entity); }
Ok, now for some reason behind my insanity. I am trying to stick to SRP, and I don't want my objects to be able to validate themselves. Therefore, my IValidatable interface is just a marker. I tried it with a marker and without it, it does not matter. I also do not want my unit tests to be cumbersome, although I know that I can have separate unit tests for validation and for the actual object.
Next, I'm pretty lazy, and I don't want to write cartographers, etc. I would also like to have a more conditional configuration, and if there is a validator, provided that it will be used.
I have used generics in many places. I like the functionality that it gave, but I'm not an expert, and now I have bitten me.
Anyway, around? A way to avoid having to throw an object so that the runtime can figure out what this refers to? I use Ninject dependency injection if this helps
UPDATE: As requested, a specific validator
public class ConcreteValidator : IValidator<SomeObject> { public IEnumerable<ValidationError> Validate(SomeObject entity) { if (string.IsNullOrEmpty(entity.Name)) yield return new ValidationError { Message = "Name is mandatory", Property = "Name" }; if (entity.Name != null && entity.Name.Length > 50) yield return new ValidationError { Message = "Name must be less than 50 characters", Property = "Name" }; } }