c# - 构建验证服务层

标签 c# validation design-patterns

<分区>

我正在寻找有关如何构建验证服务层的教程。我希望该层出现在我的“域”程序集中。目前我已经有了我的域模型和(也许不是最好的)通用存储库实现。

接下来是我的存储库实现:

public sealed class Repository<T> : Interface.IRepository<T> where T : Entity<T>
{
    private ISessionFactory sessionFactory;        

    public Repository(ISessionFactory sessionFactory)
    {                      
        this.sessionFactory = sessionFactory;
    }

    public T Get(Guid id)
    {
        using(var session = this.sessionFactory.OpenSession())
        {
            return session.Get<T>(id);
        }
    }
    public IQueryable<T> Get(Expression<Func<T, Boolean>> predicate)
    {
        using(var session = this.sessionFactory.OpenSession())
        {
            return session.Query<T>().Where(predicate);
        }
    }
    public IQueryable<T> All()
    {
        using(var session = this.sessionFactory.OpenSession())
        {
            return session.Query<T>();
        }
    }
    public void Add(T entity)
    {
        // execute validation here?

        using(var session = this.sessionFactory.OpenSession())
        using(var transaction = session.BeginTransaction())
        {
            session.Save(entity);
            transaction.Commit();
        }
    }
    public void Remove(T entity)
    {
        using(var session = this.sessionFactory.OpenSession())
        using(var transaction = session.BeginTransaction())
        {
            session.Delete(entity);
            transaction.Commit();
        }
    }
    public void Update(T entity)
    {
        // make changes &
        // execute validation here?

        using(var session = this.sessionFactory.OpenSession())
        using(var transaction = session.BeginTransaction())
        {                
            session.Update(entity);
            transaction.Commit();
        }
    }
} 

我想使用 FluentValidation验证实体。据我所知,在存储库的范围内,只有两个地方应该进行验证:添加和更新实体时。

首先我想到了 IValidator<T>作为基本实体类的参数:

public abstract class Entity<T> where T : Entity<T>
{
    // ...        
    public virtual String ValidationMessage
    {
        get;
        private set;
    }

    public virtual Boolean Validate(IValidator<T> validator)
    {
        try
        {
            validator.ValidateAndThrow(this as T);
            return true;
        }
        catch(ValidationException ex)
        {
            this.ValidationMessage = ex.Message;
            return false;
        }
    } 
    // ...      
} 

但好像不太对。

如何从设计的角度做到这一点?任何建议或教程表示赞赏。

谢谢!

最佳答案

恕我直言,问题出在您到达存储库之前。问题是在某处您允许创建无效的域对象,现在您需要验证它以确保您不会持久化它,除非它的不变量得到满足。

除了技术方面,这在您正在做的事情的概念层面上有更深层次的影响。 请记住,一个对象模拟了现实世界的一个实体:比如说,一个人的年龄为负值是否有意义?我们都同意没有人存在负年龄,因此记住现实世界和软件之间的映射,我们会看到任何 Person 对象都不应该存在负年龄,因为该模型在世界上没有它的对应物.

回到您的场景,想一想存储库:它是否适合其中的实体验证职责?这似乎比存储库应该做的要多得多。

我喜欢做的是在创建域对象之前验证构成域对象的所有参数。通过这种方式,我可以确保,如果对象被实例化,那么它一定是有效的。每当将消息发送到将导致其状态更改的对象时,您都可以执行相同的操作。

关于验证,你有一些选择:

  • 将验证类的实例传递给对象的构造函数。每次需要验证它时都传递它感觉不对,因为这意味着可能不止一个类(class)会知道正确的 IValidator<T>。用于验证。
  • 有一个类负责为您构建对象:将您的构造函数设为私有(private),并使用静态创建方法来完成正确的实例化。

这完全取决于验证需要的复杂程度。无论哪种方式,您都希望封装该决定,使其不会遍布您的代码库(仅在一个地方实例化域对象)。

关于c# - 构建验证服务层,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8680168/

相关文章:

c# - 创建新库或项目时如何设置命名空间?

c# - 编译 64 位版本的 lzo.dll

c# - 为什么我的简单 if 语句不起作用?

c# - 如何在自定义模型 Binder 中验证我的模型?

c# - 为什么以及如何修复子实体的 ASP MVC 模型验证被调用而不是父实体?

design-patterns - 领域模型中的策略模式

javascript - 以数组为参数的 Linq 查询

c# - 当组合根位于客户端时如何在 WCF 中注入(inject)依赖项

java - 不使用数据库的实体类可以吗?

java - "string-free coding"是一个常用术语吗?