C# 正在基类中检索子类类型?

C# 正在基类中检索子类类型?,c#,validation,inheritance,subclass,C#,Validation,Inheritance,Subclass,我正在尝试使用Microsoft企业验证方法在我的实体中执行验证。在我的基类中,我有以下方法: public class BaseEntity { public bool IsValid() { return Validate().IsValid; } public ValidationResults Validate() { return Validation.Validate<this.GetType()>(this); } 对于基类来

我正在尝试使用Microsoft企业验证方法在我的实体中执行验证。在我的基类中,我有以下方法:

public class BaseEntity
{
  public bool IsValid()
  {
     return Validate().IsValid;
  }

  public ValidationResults Validate()
  {
     return Validation.Validate<this.GetType()>(this);
}

对于基类来说,了解子类的任何信息都是非常不象OO的。这是它应该工作的方式


如果您想了解一些关于子类的信息,那么您需要重写此方法。

您可以将
IsValid()
Validate()
作为一个虚拟方法,以在子类中提供一些自定义定义。

将类型逻辑移出BaseEntity更干净

public class BaseEntity
{
    public bool IsValid()
    {
        return Validate().IsValid;
    }

    public ValidationResults Validate()
    {
        return Validation.Validate(this);
    }
}
public class Validation
{
    public static ValidatorResults Validator<T>( T entity )
        where T : BaseEntity
    {
        return ValidationFactory.CreateValidator(entity.GetType()).Validate(entity);
    }
}
公共类基本实体
{
公共bool是有效的()
{
返回Validate().IsValid;
}
公共验证结果验证()
{
返回验证。验证(此);
}
}
公共类验证
{
公共静态验证器结果验证器(T实体)
其中T:BaseEntity
{
返回ValidationFactory.CreateValidator(entity.GetType()).Validate(entity);
}
}

当您使用O/RM映射器(如LINQ到SQL、NHibernate或LINQ到实体(ADO.NET实体框架))时,我会使用另一种验证方法。我会保持实体完全没有验证(因此其中没有BaseEntity.Validate()。您可以将此验证逻辑移动到ObjectContext(EF)/DataContext(L2S)/Session(NH)中,并在数据库提交期间触发验证。请看下面的LINQ to SQL示例:

public partial class NorthwindDataContext
{
    public override void SubmitChanges(ConflictMode failureMode)
    {
        var invalidResults = (
            from entity in this.GetChangedEntities()
            let type = entity.GetType()
            let validator = ValidationFactory.CreateValidator(type)
            let results = validator.Validate(entity)
            where !results.IsValid
            from result in results
            select result).ToArray();            

        if (invalidResults.Length > 0)
        {
            // You should define this exception type
            throw new ValidationException(invalidResults);
        }

        base.SubmitChanges(failureMode);
    }

    private IEnumerable<object> GetChangedEntities()
    {
        ChangeSet changes = this.GetChangeSet();
        return changes.Inserts.Concat(changes.Updates);
    }
}
公共部分类NorthwindDataContext
{
公共覆盖无效提交更改(冲突模式故障模式)
{
var invalidResults=(
来自此.GetChangedEntities()中的实体
let type=entity.GetType()
让validator=ValidationFactory.CreateValidator(类型)
让结果=validator.Validate(实体)
where!results.IsValid
从结果到结果
选择结果);
如果(无效结果长度>0)
{
//您应该定义此异常类型
抛出新的ValidationException(invalidResults);
}
基本提交更改(故障模式);
}
私有IEnumerable GetChangedEntities()
{
changesetchanges=this.GetChangeSet();
返回changes.Inserts.Concat(changes.Updates);
}
}
如果您的实体无效,将引发ValidationException。您可以捕获该特定异常并迭代将在其上定义的InvalidResults属性

当您需要更多信息时,我建议您阅读这篇文章。它还介绍了如何使用实体框架来实现这一点


祝你好运。

除了所有关于验证的东西之外,还有一种方法可以对基类的方法进行编码,让它知道调用它的实际子类类型

嗯……至少是一种假装的方式(不违反任何
OO
规则,加布里埃尔)。它非常优雅,效果非常好:

public ValidationResults Validate<TEntity>(this TEntity e) where TEntity : BaseEntity
{
   return Validation.Validate<TEntity>(e);
}
公共验证结果验证(此TEntity e),其中TEntity:BaseEntity
{
返回验证。验证(e);
}

扩展方法的一大好处是……:)

实际上我喜欢这个。我最初不喜欢在实体本身中进行验证,但我能找到的唯一其他解决方案是在我的nhibernate类和实体之间创建一个非常非常薄的层(我对此不满意)。这实际上解决了很多问题,特别是在我发现的nhibernate验证器的东西上使用时(由于这篇文章)。谢谢@我很高兴你喜欢它。我从未在NHibernate上测试过它是如何工作的,所以欢迎使用任何这样的示例。我见过一些示例,主要使用NHibernate验证库(并使用xval作为抽象层)。我还没有认真研究这些示例,因为首先我将研究如何在我的应用程序中实现xval,然后从那里我将研究如何将nhibernate连接到它(我所看到的一切都很简单,就像告诉验证库将它的处理程序挂接到ISession一样)。
public ValidationResults Validate<TEntity>(this TEntity e) where TEntity : BaseEntity
{
   return Validation.Validate<TEntity>(e);
}