Lind.DDD.Domain领域模型介绍
Lind.DDD.Domain位于Lind.DDD核心项目中,它主要面向领域实体而设计,由一个IEntity的标识接口,EntityBase基类和N个Entity实体类组成,其中IEntity主要用来标识,在仓储操作时,用它来表明操作的实体范围和约束;EntityBase定义了几个公用的属性,为了避免代码的重复,特意将状态,插入时间和更新时间定义到了EntityBase里,而为何不将主键定义进来呢,主要考虑到主键的类型是为确实的,还有就是不同类型的主键可能需要实现不同的特性,如MongoDB的主键可能是BsonID或者需要为它添加BsonId这个特性,所以将主键从EntityBase中拿出来,谁需要就去实现它,也是符合面向对象的原则的.
下面我们来看一下Lind.DDD.Domain设计实体的代码
一 IEntity实体标识接口,所有poco实体都继承它
- /// <summary>
- /// 实体类标示接口
- /// </summary>
- public interface IEntity
- {
- }
二 EntityBase实体基类,具体实体基类要继承它,共享它的属性
- /// <summary>
- /// 领域模型,实体模型基类,它可能有多种持久化方式,如DB,File,Redis,Mongodb,XML等
- /// Lind.DDD框架的领域模型与数据库实体合二为一
- /// </summary>
- [PropertyChangedAttribute]
- public abstract class EntityBase :
- // ContextBoundObject,//属性变化跟踪,这个可以在具体的实体上添加,需要记录它的set变化,就添加这个特性
- IEntity,
- INotifyPropertyChanged
- {
- #region Contructors
- /// <summary>
- /// 实体初始化
- /// </summary>
- public EntityBase()
- : this(Status.Normal, DateTime.Now, DateTime.Now)
- { }
- /// <summary>
- /// 带参数的初始化
- /// </summary>
- /// <param name="status">状态</param>
- /// <param name="updateDateTime">更新日期</param>
- /// <param name="createDateTime">插入日期</param>
- public EntityBase(Status status, DateTime updateDateTime, DateTime createDateTime)
- {
- this.DataStatus = Status.Normal;
- this.DataUpdateDateTime = DateTime.Now;
- this.DataCreateDateTime = DateTime.Now;
- this.PropertyChanged += EntityBase_PropertyChanged;
- }
- #endregion
- #region Properties
- /// <summary>
- /// 建立时间
- /// </summary>
- [XmlIgnore, DataMember(Order = ), XmlElement(Order = ), DisplayName("建立时间"), Required]
- public DateTime DataCreateDateTime { get; set; }
- /// <summary>
- /// 更新时间
- /// </summary>
- [XmlIgnore, DataMember(Order = ), XmlElement(Order = ), DisplayName("更新时间"), Required]
- public DateTime DataUpdateDateTime { get; set; }
- /// <summary>
- /// 实体状态
- /// </summary>
- [XmlIgnore, DataMember(Order = ), XmlElement(Order = ), DisplayName("状态"), Required]
- public Status DataStatus { get; set; }
- #endregion
- #region Methods
- /// <summary>
- /// 拿到实体验证的结果列表
- /// 结果为null或者Enumerable.Count()==0表达验证成功
- /// </summary>
- /// <returns></returns>
- public IEnumerable<RuleViolation> GetRuleViolations()
- {
- var properties = this.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).ToArray();
- foreach (var i in properties)
- {
- var attr = i.GetCustomAttributes();
- foreach (var a in attr)
- {
- var val = (a as ValidationAttribute);
- if (val != null)
- if (!val.IsValid(i.GetValue(this)))
- {
- yield return new RuleViolation(val.ErrorMessage, i.Name);
- }
- }
- }
- }
- #endregion
- #region PropertyChangedEventHandler Events
- /// <summary>
- /// 属性值变更事件,外部可以直接订阅它
- /// </summary>
- public event PropertyChangedEventHandler PropertyChanged;
- /// <summary>
- /// 事件实例
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void EntityBase_PropertyChanged(object sender, PropertyChangedEventArgs e)
- {
- Console.WriteLine("基类EntityBase属性:{0},值:{1}", e.PropertyName, sender.GetType().GetProperty(e.PropertyName).GetValue(sender));
- }
- /// <summary>
- /// 触发事件,写在每个属性的set块中CallerMemberName特性表示当前块的属性名
- /// </summary>
- /// <param name="propertyName"></param>
- protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
- {
- if (PropertyChanged != null)
- PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
- }
- #endregion
- }
三 主键为整形的实体基类Entity,它继承了EntityBase,实现了自己的主键,所以主键为整形的实体,都要继承它
- /// <summary>
- /// 主键为int类型的实体基类
- /// </summary>
- public abstract class Entity : EntityBase
- {
- /// <summary>
- /// 标识列
- /// </summary>
- [DisplayName("编号"), Column("ID"), Required]
- public int Id { get; set; }
- }
四 主键为string类型的实体基类为NoSqlEntity,起初为了实现Mongodb表的ObjectID主键而设计的,其它的数据库如果表的主键为字符串,也可以直接继承它
- /// <summary>
- /// mongodb,xml,redis实体基类
- /// 主键类型为string
- /// </summary>
- public abstract class NoSqlEntity : EntityBase
- {
- public NoSqlEntity()
- {
- this.Id = ObjectId.GenerateNewId().ToString();
- }
- /// <summary>
- /// 标识列
- /// </summary>
- [BsonId]
- [BsonRepresentation(BsonType.ObjectId)]
- [DataMember(Order = ), XmlElement(Order = ), DisplayName("编号"), Column("ID"), Required]
- public string Id { get; set; }
- /// <summary>
- /// 返回mongodb实体的键值对
- /// </summary>
- public IEnumerable<KeyValuePair<string, object>> GetProperyiesDictionary()
- {
- var properties = this.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)
- .Where(i => i.Name != "Id")
- .ToArray();
- foreach (var i in properties)
- yield return new KeyValuePair<string, object>(i.Name, i.GetValue(this));
- }
- }
在NoSqlEntity抽象类里,我们看到了共有方法GetProperyiesDictionary(),它主要功能是将表中所有属性和它的值以键值对的方式返回一个枚举集合,我们有时在仓储类中可以直接使用这个方法,向Mongodb集成了对这种类型的支持,可以方便的实现对表
的添加与更新!
Lind.DDD.Domain实体模型除了定义实体外,还提供了实体属性的变更跟踪功能,即当一个属性值发生变化时(set 方法被触发时)我们可以跟踪到它,并进行相应的操作,一般地,我们会在使用者层,添加一种事件,使用者只要订阅了这种事件,就可以实现对
跟踪实体的操作,如把变更保存到文件,或者直接入库等等!
更多的介绍,请查看Lind.DDD源码框架的介绍
Lind.DDD.Domain领域模型介绍的更多相关文章
- Lind.DDD.Domain.IOwnerBehavor对实体的意义
回到目录 对于Lind.DDD架构,我之前写了不少文章,对于它的Domain模式也介绍了不少,像之前的IEntity,ILogicDeleteBehavor,IModifyBehavor,IStatu ...
- Lind.DDD.Domain.ISortBehavor~上移与下移
在进行列表排序时,有个“上移”和“下移”操作,这个一般在内存里完成,然后统一提交到数据库中,对于上移与下移的设计,大叔在LIND.DDD.DOMAIN里有一个ISortBehavor接口,主要是说,如 ...
- Lind.DDD敏捷领域驱动框架~Lind.DDD各层介绍
回到目录 Lind.DDD项目主要面向敏捷,快速开发,领域驱动等,对于它的分层也是能合并的合并,比之前大叔的框架分层更粗糙一些,或者说更大胆一些,在开发人员使用上,可能会感觉更方便了,更益使用了,这就 ...
- Lind.DDD敏捷领域驱动框架~介绍
回到占占推荐博客索引 最近觉得自己的框架过于复杂,在实现开发使用中有些不爽,自己的朋友们也经常和我说,框架太麻烦了,要引用的类库太多:之前架构之所以这样设计,完全出于对职责分离和代码附复用的考虑,主要 ...
- Lind.DDD.ILogicDeleteBehavor~逻辑删除的实现
回到目录 关于逻辑删除 对于逻辑删除之前的做法是在实体类中加个字段,一般是status,其中一种状态是删除,当然也有其它做法,如加个bool的字段IsDeleted,这些其实都过于武断,即它在基类里加 ...
- Lind.DDD.LindAspects方法拦截的介绍
回到目录 什么是LindAspects 之前写了关于Aspects的文章<Lind.DDD.Aspects通过Plugins实现方法的动态拦截~Lind里的AOP>,今天主要在设计思想上进 ...
- Lind.DDD.Repositories.EF层介绍
回到目录 Lind.DDD.Repositories.EF以下简称Repositories.EF,之所以把它从Lind.DDD中拿出来,完全出于可插拔的考虑,让大家都能休会到IoC的魅力,用到哪种方法 ...
- Lind.DDD.Repositories.Redis层介绍
回到目录 之前已经发生了 大叔之前介绍过关于redis的文章,有缓存,队列,分布式pub/sub,数据集缓存以及仓储redis的实现等等,而今天在Lind.DDD的持久化组件里,redis当然也有一席 ...
- Lind.DDD.Events领域事件介绍
回到目录 闲话多说 领域事件大叔感觉是最不好讲的一篇文章,所以拖欠了很久,但最终还是在2015年年前(阴历)把这个知识点讲一下,事件这个东西早在C#1.0时代就有了,那时学起来也是一个费劲,什么是委托 ...
随机推荐
- PHP类的封装和做投票和用进度条显示
三处理传过来的数据1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http:// ...
- Liferay7 BPM门户开发之38: OSGi模块化Bndtools、Maven、Gradle开发构建入门
前言 OSGi是目前动态模块系统的事实上的工业标准,它适用于任何需要模块化.面向服务.面向组件的应用程序.Eclipse如此庞大和复杂的插件体系,就是基于OSGi.Liferay也是基于OSGi.OS ...
- 谈谈关键字strictfp
Java语言中的其中一个设计目标是可移植性.无论在哪个虚拟机上运行,同一个计算应该得到同样的结果.对于浮点数的算术运算,实现这样的可移植性是相当困难的.double 类型使用 64 位存储一个 do ...
- ClickOnce部署(5):自定义安全权限
今天我们来探讨一下在ClickOnce部署中如何严格控制应用程序的权限. 演示应用 为了在下文中能更好地演示,我们先要做一个测试项目.也为了显得简单易懂,我使用最常用且最常见的WinForm项目,这是 ...
- javascript运动系列第七篇——鼠标跟随运动
× 目录 [1]眼球转动 [2]苹果菜单[3]方向跟随 前面的话 运动除了直线运动和曲线运动两种运动形式外,还有一种运动形式是鼠标跟随运动,而这种跟随运动需要用到三角函数的相关内容或者需要进行比例运算 ...
- JBOSS.71.1.Final安装配置
对于JBOSS大家了解多少,相信做Java开发的小童鞋对于Tomcat一定不陌生,而今天为大家介绍的JBOSS也是一款服务器软件,相比Tomcat,JBOSS对于高级的JavaEE相对来说更强大一点, ...
- 深入理解 OWIN 中的 Host 和 Server
The Open Web Interface for .NET (OWIN),注意单词为大写,之前好像都写成了 Owin,但用于项目的时候,可以写成:Microsoft.Owin.*. OWIN 体系 ...
- IDDD 实现领域驱动设计-SOA、REST 和六边形架构
上一篇:<IDDD 实现领域驱动设计-架构之经典分层> 阅读目录: SOA-面向服务架构 REST 与 RESTful 资源(Resources) 状态(State) 六边形架构 DDD ...
- Mysql5.0没有nvarchar,national
mysql采用utf-8编码,而传统的数据库采用unicode,一个汉字要用两个unicode的char,而在mysql中由于使用了utf-8,所以无论汉字还是字母,都是一个长度的char,所以就不用 ...
- Visual Studio Code 智能提示文件
Visual Studio Code 开发前端和node智能提示 visual studio code 是一个很好的编辑器,可以用来编写前端代码和nodejs. 我很喜欢使用VSC,现在流行框架对VS ...