通过执行以下操作,我获得了已修改和新实体的列表.
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"); } }
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界面只是一个标记.我有没有标记尝试过,没有区别.我也不希望我的单元测试体积庞大,但我知道我可以对验证和实际实体进行单独的单元测试.
接下来我很懒,而且我不想写mappers等.另外我想对配置有更多的约定,如果有一个验证器提供它将被使用.
我在很多地方都使用过泛型.我喜欢它给出的功能,但我不是专家,现在它正在咬我.
有没有办法解决?一种避免必须转换对象的方法,以便运行时可以找出将其转换为什么?如果有帮助,我正在使用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" }; } }
解决方法
我也不明白你的代码究竟发生了什么,因为下面的代码段可行.所以请将你的所有课程发布给你
public interface IValidator<T> where T: IObj { } public class PersonValidator : IValidator<Person> { } public static class Validators { public static IValidator<TObject> GetValidator<TObject>(TObject obj) where TObject : IObj { var t = obj.GetType(); var name = string.Format("{0}.{1}Validator",t.Namespace,t.Name); return (IValidator<TObject>) Activator.CreateInstance(Type.GetType(name)); } } [TestFixture] public class ValidatorsTest { [Test] public void TestPersonValidator() { var pValidator = Validators.GetValidator(new Person()); } }
您遇到的问题如下
var entities = (ObjectStateManager.GetobjectStateEntries(EntityState.Added | EntityState.Modified)) .Select(ose => ose.Entity).OfType<IValidatable>();
foreach(实体中的var实体)
{
var validator = validatorProvider.GetValidator(entity);
var errors = validator.Validate(entity);
if(errors.Count()> 0)
{
抛出新的异常(“验证错误”);
}
}
这里当你调用validatorProvider.GetValidator(实体)时,实体的类型是IValidator,所以你要调用validatorProvider.GetValidator< IValidator>(entity),但你真正想做的是validatorProvider.GetValidator< TEntity>(entity)
你需要用反射调用泛型方法,动态指定要调用的方法.
最后,使用反射调用适当的方法,最好将方法声明更改为GetValidator< TObject>()并执行以下操作:
foreach(var entity in entities) { var validator = validatorProvider.GetType().getmethod("GetValidator").MakeGenericmethod(entity.GetType()).Invoke(validatorProvider,null ); var errors = validator.Validate(entity); if (errors.Count() > 0) { throw new Exception("A validation error"); } }
最后修订:
.... foreach(var entity in entities) { GetType() .getmethod("ValidateObj") .MakeGenericmethod(entity.GetType()) .Invoke(this,null ); } .... .... public void ValidateObj<TEntity>(TEntity obj) where TEntity : IValidatable { var errors = validatorProvider.GetValidator<TEntity>().Validate(obj); if (errors.Count() > 0 ) throw new ValidationException(obj,errors); }
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。