XAF-Domain Components 技术 使用接口来定义ORM业务对象
一、简介
- 可以创建可重用的领域对象:多数情况下,每个XAF中用到的领域对象都不是唯一的,比较常见的对如:人、电话、地址,等领域对象,这些使用频率较高的,想要抽象出来还是有点难度的,这不是一个简单的任务,使用DC这事就简单了。
- 可以使用多重继承:因为DC是用接口描述的,所以,多继承在C#的语法级别被支持,你可以使用继承以前写过的DC,重用它,并且可以增加新的属性和替换逻辑。事实上,这是我最喜欢的一个特性!
- 不需要从持久性化基类继承实现领域对象 :最终的执行代码是生成的,这当然很容易实现了。当然,也可以指定基类。
- 在Medium Trust 环境中,DC组件不能使用。
- DC组件技术不支持Model First和Database first的方式。我们不推荐使用附加(就是两个或多个)数据库。因此,我们不提供任何手段从现有数据库生成域组件代码和逻辑,我们有没有立即的计划来支持此方案。请试试 XPO 或实体框架数据模型。
- 自定义字段不能在设计时添加到域组件。
- 如果一个DC组件注册为SharePart,不能添加自定义字段。
二、DC定义
[DomainComponent] public interface IPerson {string LastName { get; set; }string FirstName { get; set; }string FullName { get; }void Copy(IPerson target); }
你可以看到,接口上必须使用DomainComponentAttribute 来声明接口是个DC.接口的属性就是将来出来表的字段.在普通BO定义中使用的一些Attribute现在仍可用.例如你可以给LastName 上面加上 RuleRequiredFieldAttribute, 给接口上加上 NavigationItemAttribute. FullName 被定义为只读的.它需要在logic类中定义实现.另外Copy方法也必须在logic中实现.
三、注册DC
只有注册了DC后,才会被XAF生成真正的XPO类,下面是注册方法,需要打开Module.cs文件,实override下面的方法:
using DevExpress.Persistent.BaseImpl; // ... public override void Setup(XafApplication application) {base.Setup(application);XafTypesInfo.Instance.RegisterEntity("Person", typeof(IPerson)); }
上面的注册中,并没有指定基类,所以将会默认使用DCBaseObject 做为基类,如果要指定基类,可以看下RegisterEntity的其它重载方法。
四、Domain Logic
每个DC可以有一(零)个或多个Domain Logic. Domain Logic 是一个普通的类,加上了 DomainLogicAttribute 标记, 并指定DC类型. 其实再多的话都没有一个代码实例有用:
[DomainLogic(typeof(IPerson))] //必须写个,IPerson是指为哪个DC的逻辑 public class PersonLogic { //类别是任意的public const string FullNameSeparator = " ";public string Get_FullName(IPerson person) { //Get_XXX Get_是固定的,实现property的get的方法,FullName是属性的名称return string.Format("{0}{1}{2}", person.FirstName, FullNameSeparator, person.LastName);}public static void Copy(IPerson person, IPerson target) { //实现了上面定义的Copy方法,但是,注意,第一个参数,在接口中并没有定义,但在这里却可以出现,也可以不出现,调用时会被自动替换为当前对象if(target != null) {target.FirstName = person.FirstName;target.LastName = person.LastName;}} }
上面的示例中,还可以看到,Get_FullName是非静态的,Copy是静态的,事实上,是不是静态的都没有关系,都会被调用,当然,你可以想像一下,静态方法是不需要实例化对象的。将来被调用时,是不会实例化PersonLogic这个类的。
否则就会实例化。当然,类中一个非静态方法都没有时,才会不实例化logic类。
那么,DC中的语法到底有多少呢?
说明 | 示例 |
---|---|
Get_属性名称 当property的get被调用时,就执行这个方法。 |
public static string Get_FullName(IMyInterface instance) public static string Get_FullName(IMyInterface instance, IObjectSpace objectSpace)
|
Set_属性名 当property的set被调用时,就执行这个方法。 |
public static void Set_FullName(IMyInterface instance, string value) public static void Set_FullName(IMyInterface instance, IObjectSpace objectSpace, string value)
|
BeforeChange_属性名 当属性被设置新值之前被调用 |
public static void BeforeChange_FirstName(IMyInterface instance, string value) public static void BeforeChange_FirstName(IMyInterface instance, IObjectSpace objectSpace, string value)
|
AfterChange_属性名 当属性被设置新值之后被调用. |
public static void AfterChange_FirstName(IMyInterface instance) public static void AfterChange_FirstName(IMyInterface instance, IObjectSpace objectSpace)
|
方法名称 接口上定义了一个方法定义,那个方法被调用时,执行此处的逻辑。 |
public static void CalculateSalary(IMyInterface instance, int amount, int price) public static void CalculateSalary(IMyInterface instance, IObjectSpace objectSpace, int amount, int price)
|
AfterConstruction Bo中有也有这个,就是新建对象完成后,可以在这里写一些初始化属性值的操作。 |
public static void AfterConstruction(IMyInterface instance) public static void AfterConstruction(IMyInterface instance, IObjectSpace objectSpace)
|
OnDeleting Bo中也有这个,当删除时执行。 |
public static void OnDeleting(IMyInterface instance) public static void OnDeleting(IMyInterface instance, IObjectSpace objectSpace)
|
OnDeleted Bo中有,删除后执行。 |
public static void OnDeleted(IMyInterface instance) public static void OnDeleted(IMyInterface instance, IObjectSpace objectSpace)
|
OnSaving Bo中有也有这个,保存中执行。 |
public static void OnSaving(IMyInterface instance) public static void OnSaving(IMyInterface instance, IObjectSpace objectSpace)
|
OnSaved Bo中有也有这个,保存完成执行。 |
public static void OnSaved(IMyInterface instance) public static void OnSaved(IMyInterface instance, IObjectSpace objectSpace)
|
OnLoaded Bo中有也有这个,已经的对象,被加载后执行。 |
public static void OnLoaded(IMyInterface instance) public static void OnLoaded(IMyInterface instance, IObjectSpace objectSpace)
|
上面的方法,必须是静态或是非静态的,必须为public,参数的定义可以是以下几种情况:
LogicMethodName(source_parameters)
与DC中定义的方法是一致的。LogicMethodName(target_interface, source_parameters)
当前DC类型,指当前对象和接口中定义的那些参数.LogicMethodName(target_interface, object_space, source_parameters)
与上面的相对,多了一个object_space,用过xpo+xaf的同学一看就懂了,就是指当前对象用的objectspace,因为有时我们需要使用objectspace进行一些crud操作.
五、示例:
之前的Logic你看起来可能感觉有点麻烦,下面来看看一种简写方法:
[DomainComponent] public interface IPerson {string FirstName { get; set; }[NonPersistentDc]string FullName { get; set; } } [DomainLogic(typeof(IPerson))] public class PersonLogic {IPerson person;public PersonLogic(IPerson person) {this.person = person; //构造逻辑时就传入了当前对象}//像BO中一样直接写propertypublic string FullName {get { return person.FirstName; }set { person.FirstName = value; }} }
下面是静态的实现方法:
[DomainComponent] public interface IContact {static string Name { get; } } [DomainLogic(typeof(IContact))] public class ContactLogic {public static string Name {get { return "a constant string"; }} }
下面是如何使用ObjectSpace的示例:
[DomainLogic(typeof(IPerson))] public class AdditionalPersonLogic {public static void AfterConstruction(IPerson person, IObjectSpace objectSpace) {person.Address = objectSpace.CreateObject<IAddress>();} }
下面来看看重写别的DC中定义的逻辑
[DomainComponent] public interface IPerson {[ImmediatePostData]string FirstName { get; set; }[ImmediatePostData]string LastName { get; set; }string DisplayName { get; } } [DomainLogic(typeof(IPerson))] public class IPerson_Logic {public string Get_DisplayName(IPerson person) {return person.FirstName + " " + person.LastName;} } [DomainComponent] public interface IClient : IPerson {[ImmediatePostData]string ClientID { get; set; } } [DomainLogic(typeof(IClient))] public class IClient_Logic {public string Get_DisplayName(IClient client) { //这里重写了IPerson_Logic中的定义,相当于bo中的overridereturn client.ClientID;} }
下面演示了如何为collection属性返回值:
[DomainComponent] public interface IOrder {[NonPersistentDc]IList<IOrderLine> OrderLines { get; } } [DomainLogic(typeof(IOrder))] public class OrderLogic {public IList<IOrderLine> Get_OrderLines(IOrder order) {//... } }
下面的IUser并不是一个DC定义(没用[DomainComponent]来定义,这时,必须在逻辑中为IsActive和UserName两个属性的实现。否则是不能运行通过的。
public interface IUser {bool IsActive { get; set; }string UserName { get; } } [DomainComponent] public interface IPerson : IUser {string LastName { get; set; }string FirstName { get; set; } }
在程序集包含DC组件时,可以通过过 ITypesInfo.RegisterEntity 方法来注册,你也可以通过 ITypesInfo.RegisterDomainLogic 和 ITypesInfo.UnregisterDomainLogic 的方法手动注册逻辑,当你不能访问DC Logic类来源,但需要操作DC逻辑分配时这很有用。
六、一对多和多对多关系的定义
在DC中,你不需要使用 Association来定义一对多和多对多关系.下面的代码片段演示了如何定义订单与订单明细关系.
[DomainComponent] public interface IOrder {IList<IOrderItem> Items { get; } } [DomainComponent] public interface IOrderItem {IOrder Order { get; set; } }
下面是多对多关系:
[DomainComponent] public interface IEmployee {IList<ITask> Tasks { get; } } [DomainComponent] public interface ITask {IList<IEmployee> Employees { get; } }
你可以只定义一端的属性,比如,IEmplyee.Tasks,另一端的,将会自动生成。当然在XAF的界面中,ITask.Employees将不会被显示出来。
下面的情况时,生成器不知道该如何生成代码,所以需要BackReferenceProperty来指定对方的属性:
[DomainComponent] public interface IAccount {[BackReferenceProperty("AccountOne")]IList<IContact> ContactA { get; }[BackReferenceProperty("AccountTwo")]IList<IContact> ContactB { get; }IList<IContact> ContactC { get; } } [DomainComponent] public interface IContact {string Name { get; set; }IAccount AccountOne { get; set; }IAccount AccountTwo { get; set; }IAccount AccountThree { get; set; } }
七、Shared Parts
当一个DC被几个DC同时继承时,这个DC必须要注册为SharePart,使用ITypesInfo.RegisterSharedPart 方法完成.
[DomainComponent] public interface IWorker { }[DomainComponent] public interface IManager : IWorker { }[DomainComponent] public interface IEvangelist : IWorker { }public class MyModule : ModuleBase {// ... public override void Setup(XafApplication application) {base.Setup(application);XafTypesInfo.Instance.RegisterEntity("Manager", typeof(IManager));XafTypesInfo.Instance.RegisterEntity("Evangelist", typeof(IEvangelist));XafTypesInfo.Instance.RegisterSharedPart(typeof(IWorker)); //<-----这里} }
八、DC特有的Attribute
除了XAF中在BO中使用的Attribute,DC又增加了几个Attribute:
Attribute | 说明 |
---|---|
BackReferencePropertyAttribute | 前面已经看到了,是用来明确的指定对方属性的。 |
CreateInstanceAttribute | Applied to methods. Specifies that a Domain Component's target method will create Domain Component instances. |
DomainComponentAttribute | 用了这个,接口才叫DC。 |
DomainLogicAttribute | DC逻辑类标识。 |
NonPersistentDcAttribute | 非持久化的DC,使用时也需要标识上DomainComponentAttribute |
PersistentDcAttribute | 与BO中的PersistentAttribute 是一样的。可以指定一个表名。 |
转载于:https://www.cnblogs.com/chenliyang/p/6543816.html
XAF-Domain Components 技术 使用接口来定义ORM业务对象相关推荐
- (转载)虚幻引擎3--13掌握虚幻技术UnrealScript 接口
第十三章 – 接口 什么是接口? 接口示例 USB 电脑鼠标 电源插座 编程说明 定义接口 声明和定义 接口继承 实现接口 为什么使用接口? 结束语 指南 13.1 – 指南针, 第一部分:指南针接口 ...
- matlab数据接口技术,matlab接口技术与应用
matlab接口技术与应用 来源:mamingkeda 作者:华仔 浏览:1070 时间:2016-08-10 14:18 标签: 摘要: matlab接口技术与应用应用程序接口的使用方法.全书分为1 ...
- 华为交换机默认vlan都是通的吗_华为设备二层交换技术——Hybrid接口详解
Hybrid接口的特点 按照VLAN接口封装类型,华为交换机的接口主要有三种模式:Access.Trunk和Hybrid.其中Access.Trunk接口和Cisco技术并无差异,Hybrid接口是华 ...
- 计算机接口及应用技术,计算机接口技术及应用 第9讲 控制网络技术(2 现场总线).pdf...
计算机接口技术及应用 第9讲 控制网络技术(2 现场总线).pdf (9页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 15.9 积分 1<计算机接 ...
- 技术分享 | 接口自动化测试中如何对xml 格式做断言验证?
在服务端自动化测试过程中,发起请求之后还需要对响应值进行验证,验证响应信息符合预期值之后,这一条接口自动化测试用例才算完整的通过.所以这一章节,将会讲解在接口自动化测试中,是如何对服务端返回的 XML ...
- Web 开发技术API 接口参考
Web 开发技术 https://developer.mozilla.org/zh-CN/docs/Web Web API 接口参考 https://developer.mozilla.org/zh- ...
- OpenCV3.3中主成分分析(Principal Components Analysis, PCA)接口简介及使用
OpenCV3.3中给出了主成分分析(Principal Components Analysis, PCA)的实现,即cv::PCA类,类的声明在include/opencv2/core.hpp文件中 ...
- 毕业论文中使用的技术—FileReader接口
用来把文件读入内存,并且读取文件中的数据. FileReader接口提供了一个异步API,使用该API可以在浏览器主线程中异步访问文件系统,读取文件中的数据 FileReader接口的方法 方法名 参 ...
- 微机原理与接口技术:接口概述 详细笔记
文章目录 1.接口的概念 2.接口的工作方式 3.接口的逻辑 4.接口设计过程 1.接口的概念 接口传送的三类信息:数据信息.控制信息.状态信息. 计算机如何区分输入数据和输出数据:大部分计算机都把I ...
最新文章
- Hibernate连接池配置实例
- 关于5G技术和5G技术即将面临的各项挑战
- 【PHP】xampp配置多个监听端口和不同的网站目录(转)
- 【调试】Linux下超强内存检测工具Valgrind
- 学习笔记(02):Python网络编程并发编程-assert断言的用途
- layui 分页ajax,实现Ajax异步的layui分页
- FreeBSD学习笔记15-FreeBSD下安装Apache
- 函数 的 重载 和 函数 模版
- 史上最全Html和CSS布局技巧
- mysql 聚集函数 count 使用详解(转载)
- java数组基本操作
- 【踩坑】XML转JSON中如何把单个元素转成数组
- 全国青少年软件编程(Scratch)等级考试一级考试真题2022年12月——持续更新.....
- MATLAB | 那些你不得不知道的MATLAB小技巧(一)
- 免费开源解压缩软件7-Zip
- 项目中站立会议和故事墙的那些事儿—敏捷开发
- find -perm 里的 + -的含义
- Excel中如何添加Power Pivot
- iPhone X用户需要知道的12个隐藏小技巧 条条实用
- CMMI的五个级别及其特征简述
热门文章
- 程序员伤不起的年龄——30岁
- R语言入门第六集 实验五:综合应用
- MYSQL的字符序_mysql字符序核心概念
- sql int转换为varchar_常见SQL优化实践
- vs中如何开发mysql_VS2015如何连接mySQL数据库图文
- mysql和redis统计网站活跃度,最代码网站用户私信列表采用mysql union查询优化为Redis查询的经验和相关代码片段分享...
- 如何查找历史线程阻塞原因_java并发编程-线程状态,线程阻塞方式,阻塞中的线程如何终止?...
- java.net import_import java.net.URL;是什么类?
- 7.QML Qt Quick——基于Qt Quick Controls 2实现图片浏览器
- C++知识点6——数组与指针初步