[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中实现.数据库
using DevExpress.Persistent.BaseImpl; // ... public override void Setup(XafApplication application) { base.Setup(application); XafTypesInfo.Instance.RegisterEntity("Person", typeof(IPerson)); }
上面的注册中,并无指定基类,因此将会默认使用DCBaseObject 作为基类,若是要指定基类,能够看下RegisterEntity的其它重载方法。express
每一个DC能够有一(零)个或多个Domain Logic. Domain Logic 是一个普通的类,加上了 DomainLogicAttribute 标记, 并指定DC类型. 其实再多的话都没有一个代码实例有用:app
[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类。ide
那么,DC中的语法到底有多少呢?ui
说明 | 示例 |
---|---|
Get_属性名称this 当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)
LogicMethodName(target_interface, source_parameters)
LogicMethodName(target_interface, object_space, source_parameters)
以前的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中同样直接写property public 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中的override return 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; } }
当一个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)); //<-----这里 } }
除了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 是同样的。能够指定一个表名。 |