构建验证服务层

时间:2011-12-30 13:54:07

标签: c# validation design-patterns

我正在寻找有关如何构建验证服务层的教程。我想让图层出现在我的'domain'程序集中。目前我已经拥有了我的域模型和(可能不是最好的)通用存储库实现。

我的存储库实现是下一步:

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;
        }
    } 
    // ...      
} 

但它似乎不对。

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

谢谢!

1 个答案:

答案 0 :(得分:0)

恕我直言,问题就在于你到达存储库之前。问题在于你允许创建一个无效的域对象,现在你需要验证它以确保你没有持久化它,除非它的不变量得到满足。

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

回到您的场景,想一想存储库:它是否适合实体验证的责任?这似乎远不是存储库应该做的。

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

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

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

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