Я использую Entity Framework v4. Я пытаюсь реализовать некоторую логику для проверки моих сущностей перед их сохранением путем переопределения метода SaveChanges. Я также POCO для моих лиц.
Я получаю список измененных и новых объектов, выполнив следующее.
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");
}
}
А вот код для моего метода GetValidator:
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;
}
Проблема в том, что я получаю сообщение об ошибке:
Unable to cast object of type 'Blah.Validation.ConcreteValidator' to type 'Blah.Validation.IValidator`1[Blah.Validation.IValidatable]'
Единственное, что я могу сделать, чтобы избавиться от этой ошибки, - сначала привести объект к нужному типу, но я не хочу, чтобы все приводилось.
Вот мой интерфейс для IValidator
public interface IValidator<TEntity>
where TEntity : IValidatable
{
IEnumerable<ValidationError> Validate(TEntity entity);
}
Хорошо, теперь по какой-то причине моего безумия. Я пытаюсь придерживаться SRP и не хочу, чтобы мои объекты могли сами себя проверять. Так что мой интерфейс IValidatable - это просто маркер. Я пробовал с маркером и без него, без разницы. Я также не хочу, чтобы мои модульные тесты были громоздкими, хотя я знаю, что у меня могут быть отдельные модульные тесты для проверки и для реальной сущности.
Далее я довольно ленив и не хочу писать мапперы и т. Д. Кроме того, я хотел бы иметь больше соглашений по конфигурации, и если есть валидатор, при условии, что он будет использоваться.
Я использовал дженерики во многих местах. Мне нравится функциональность, которую он дал, но я не эксперт, и в данный момент это кусает меня.
Есть ли что-нибудь вокруг этого? Способ избежать приведения объекта к объекту, чтобы среда выполнения могла выяснить, к чему его привести? Я использую инъекцию зависимостей Ninject, если это помогает
UPDATE:
По запросу, конкретный валидатор
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" };
}
}