c# – 如何避免投射但传递正确的类型
我正在使用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界面只是一个标记.我有没有标记尝试过,没有区别.我也不希望我的单元测试体积庞大,但我知道我可以对验证和实际实体进行单独的单元测试. 接下来我很懒,而且我不想写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" }; } } 解决方法
我建议你有验证器的服务定位器,并根据你的类型验证器的类型参数得到验证器,你可以找到如何做的例子
here
我也不明白你的代码究竟发生了什么,因为下面的代码段可行.所以请将你的所有课程发布给你 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实体) 这里当你调用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); } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- c# – 无法安装Microsoft Power Bi Postgre SQL连接器
- 官方的正则表达式组件 RegularExpressions (3) : TMatchEva
- c# – .net对象资源管理器控件
- Ruby rubocop:如何冻结用splat生成的数组常量
- Flash反编译软件ASV2013能否分析使用过Adobe Alchemy的SWF文
- jsonp详解
- 【android,4】4.SQLite数据库,内容提供者、内容观察者
- BlazeDS Spring Security Integration问题一点总结
- flex的一些函数随机数random(),round(),ceil(),floor()
- XML publicId和systemId