业务逻辑层的设计(二)——让领域模型支持验证

在之前的随笔《业务逻辑层的设计(一)》已经提到了领域对象模型如何支持验证了。

本篇随笔将对领域模型继续强化。

DomainObject为所有领域模型的基类,只要让我们的领域模型继承这个基类,也就实现了通用的验证接口ISupportsValidation。

ConstraintValidator中封装了使用验证框架的操作,配合ValidationErrorValidationError使外界调用不需要了解验证框架的API。

 

    public interface ISupportsValidation
    {
        bool IsValid { get; }
        IList<ValidationError> Validate();
    }

ISupportsValidation接口使得所有的领域模型都具备验证的功能,而DomainObject则实现了具体的验证,使得我们所有的领域模型都有通用的验证模块。

    /// <summary>
    /// 所有领域模型的基类
    /// </summary>
    public class DomainObject:ISupportsValidation
    {
        public virtual bool IsValid
        {
            get
            {
                try
                {
                    return ConstraintValidator.IsValid(this);
                }
                catch
                {
                    return false;
                }
            }
        }

        IList<ValidationError> ISupportsValidation.Validate()
        {
            IList<ValidationError> errors;
            errors = (IList<ValidationError>)ConstraintValidator.Validate(this);
            return errors;
        }
    }


其中的ConstraintValidator类中引用了微软企业库5.0的验证模块,这个设计是为了保持其他层对验证框架的透明化,使用时也就不必引用验证框架了。

    using Microsoft.Practices.EnterpriseLibrary.Validation;

    public class ConstraintValidator
    {
        public static bool IsValid(DomainObject domainObj)
        {
            ValidationResults results = Validation.Validate(domainObj);
            return results.IsValid;
        }

        public static IList<ValidationError> Validate(DomainObject domainObj)
        {
            IList<ValidationError> errors = new List<ValidationError>();
            ValidationResults results = Validation.Validate(domainObj);
            if (!results.IsValid)
            {
                foreach (ValidationResult result in results)
                {
                    ValidationError error = new ValidationError();
                    error.Key = result.Key;
                    error.Message = result.Message;
                    errors.Add(error);
                }
            }
            return errors;
        }

    }


使用微软企业库来简化代码的复杂度,将会看到User继承了DomainObject,

但是在领域模型中还是需要引入using Microsoft.Practices.EnterpriseLibrary.Validation命名空间和属性,

但比起完全自己动手写规则,的确要简化很多了。

    public class User : DomainObject
    {
        private Department _department = new Department();
        private IList<Role> _roles = new List<Role>();
        /// <summary>
        /// ID
        /// </summary>
        [NotNullValidator(MessageTemplate="标识不能为空")]
        public virtual int ID
        {
            get;
            set;
        }
        /// <summary>
        /// LoginName
        /// </summary>
        [StringLengthValidator(50, MessageTemplate = "登录名称必须在50个字符以内")]
        public virtual string LoginName
        {
            get;
            set;
        }
        /// <summary>
        /// Password
        /// </summary>
        [StringLengthValidator(20, MessageTemplate = "密码长度必须在20个字符以内")]
        public virtual string Password
        {
            get;
            set;
        }
        /// <summary>
        /// DepartmentID
        /// </summary>
        public virtual Department Department
        {
            get { return _department; }
            set { _department = value; }
        }
        /// <summary>
        /// Name
        /// </summary>
        public virtual string Name
        {
            get;
            set;
        }

        /// <summary>
        /// CreateTime
        /// </summary>
        public virtual DateTime CreateTime
        {
            get;
            set;
        }

        /// <summary>
        /// Roles
        /// </summary>
        public virtual IList<Role> Roles
        {
            get { return _roles; }
            set { _roles = value; }
        }

        
    }


可以发现领域模型比上一次的要简洁很多,细心的同学应该发现类中使用了许多virtual,

那是为了支持数据访问层的延迟加载功能,关于延迟加载原理可以看下 另一篇

 

让我们来体验一下吧

        [Test]
        public void TranRollbackTest()
        {
            IDataContext context = DataContextFactory.GetDataContext();
            User user1 = new User() { Name = "adama1", Password = "123123" };
            User user2 = new User() { Name = "adama2", Password = "123123" };
            if (!user1.IsValid)
            {
                ISupportsValidation user1Vali = user1;
                IList<ValidationError> errors= user1Vali.Validate();
                foreach (ValidationError error in errors)
                {
                    Console.WriteLine("{0}:{1}",error.Key,error.Message);
                }
            }
            context.BeginTransaction();
            context.Add(user1);
            context.Add(user2);
            context.Rollback();
        }

由于我们在LoginName属性加了验证条件,所以验证并不会通过,

输出结果:LoginName:登录名称必须在50个字符以内

 

上面的context是我探索ORM原理时自制的上下文,也是一个用到了前一篇提到的工作单元uow,暂时不必理会。

posted @ 2013-07-16 02:19  十三燕  阅读(2475)  评论(0编辑  收藏  举报