以下是获取修改和新实体列表的代码:
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的依赖注入。
更新: 根据要求,具体的验证器如下:
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" };
}
}
ConcreteValidator
的定义。 - Péter Török