[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 是同樣的。能夠指定一個表名。 |