加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 如何避免投射但传递正确的类型

发布时间:2020-12-15 21:11:47 所属栏目:百科 来源:网络整理
导读:我正在使用Entity Framework v4.我试图通过覆盖SaveChanges方法来实现一些逻辑来验证我的实体,然后再保存它们.我也是我的实体的POCO. 通过执行以下操作,我获得了已修改和新实体的列表. var entities = (ObjectStateManager.GetObjectStateEntries(EntityStat
我正在使用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实体)
{
????????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);
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读