[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後,才會被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的其它重載方法。
每個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被調用時,就執行這個方法。
如果屬性是只有get或,非持久化時,才可以實現這個,否則都自動實現。
public static string Get_FullName(IMyInterface instance)
public static string Get_FullName(IMyInterface instance, IObjectSpace objectSpace)
Set_屬性名
當property的set被調用時,就執行這個方法。
屬性必須不能是只讀的,即,DC中聲明了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: