將委托持久化及利用表達式樹從持久化庫還原委托
阿新 • • 發佈:2017-05-24
限定 pre ole 表示 eth persist static tor .get
在領域事件中,有時為了數據的一致性,需要先將事件持久化,然後在讀取數據時還原並執行事件保證數據一致。
持久化委托時,我們需要持久化委托的類型、方法名稱和方法參數類型。
如申明一個委托:
public delegate void DomainEventHandler(object sender, BaseDomainEventArgs eventArgs);
定義一個事件:
public static event DomainEventHandler HelloDomainEvent;
獲取事件訂閱委托列表,並獲取委托的類型、方法名稱和方法參數類型
1 foreach (var item in HelloDomainEvent.GetInvocationList())//按照調用順序返回此多路廣播委托的調用列表。 2 { 3 var eventType = item.Target.GetType().AssemblyQualifiedName;//獲取當前委托調用者的 System.Type 的程序集限定名,其中包括從中加載 System.Type 的程序集的名稱 4 var eventMethodName = item.Method.Name;//獲取委托表示方法的名稱 5 var eventMethodParamaters = item.Method.GetParameters();//獲取委托表示方法的參數 6 String[] eventMethodParamaterTypes = new String[eventMethodParamaters.Length];//委托表示方法的參數類型 7 var index = 0; 8 foreach (var paramater in eventMethodParamaters) 9 { 10 eventMethodParamaterTypes[index] = paramater.ParameterType.AssemblyQualifiedName;//獲取參數的System.Type 的程序集限定名,其中包括從中加載 System.Type 的程序集的名稱 11 index++; 12 } 13 }
可以將 eventType ,eventMethodName ,eventMethodParamaterTypes 持久化在數據庫或本地文件中。
接下來是從持久化庫中還原委托:
1 private TDelegator CreateDelegator<TDelegator>(String strEventType,String eventMethodName,String[] strEventMethodParameterTypes) 2 { 3 var eventType = Type.GetType(strEventType); //獲得委托調用者類型 4 var target = eventType.Assembly.CreateInstance(eventType.FullName); //實例化委托調用者 5 var targetConstant = Expression.Constant(target, eventType); //創建委托調用常量表達式 6 7 ParameterExpression[] arguments = new ParameterExpression[strEventMethodParameterTypes.Length];//創建參數表達式數組 8 9 var index = 0; 10 foreach (var item in strEventMethodParameterTypes) 11 { 12 arguments[index] = Expression.Parameter(Type.GetType(strEventMethodParameterTypes[index]));//創建參數表達式,並將其賦值給數表達式數組 13 index++; 14 } 15 16 var methodCallExp = Expression.Call(targetConstant, eventType.GetMethod(eventMethodName), arguments);//創建一個表示調用帶參數的方法的MethodCallExpression。 17 //Expression.Lambda<TDelegator>(methodCallExp, arguments) 返回以表達式目錄樹的形式將強類型 lambda 表達式表示為數據結構的 Expression<TDelegate> 18 //Expression<TDelegate>.Compile() 將表達式樹描述的 lambda 表達式編譯為可執行代碼,並生成表示該 lambda 表達式的委托 19 return Expression.Lambda<TDelegator>(methodCallExp, arguments).Compile(); 20 }
為了保證數據一致,我們在執行還原的委托時還需要知道當時委托傳入的參數,所以在持久化委托時,我們還要獲取到委托傳入的參數,並持久化。
簡單示例:
1 /// <summary> 2 /// 領域事件委托 3 /// </summary> 4 /// <param name="sender"></param> 5 /// <param name="eventArgs"></param> 6 /// <summary> 7 public delegate void DomainEventHandler(object sender, BaseDomainEventArgs eventArgs); 8 public class DomainEventTest2 : BaseTest 9 { 10 /// 事件 11 /// </summary> 12 public static event DomainEventHandler HelloDomainEvent; 13 14 private List<Dictionary<String, Object>> eventStort = new List<Dictionary<string, Object>>();//事件及調用參數持久化 15 16 public override void Test() 17 { 18 var chinaSayHelloHandler = new ChinaSayHelloHandler(); 19 var englishSayHelloHandler = new EnglishSayHelloHandler(); 20 { 21 HelloDomainEvent += chinaSayHelloHandler.Handler; 22 HelloDomainEvent += englishSayHelloHandler.Handler; 23 WriteLine("持久化事件中。。。"); 24 Persistence(HelloDomainEvent, new SayEventArgs() { Message = "在見面時打招呼" }); 25 WriteLine("持久化事件完成"); 26 } 27 { 28 WriteLine("加載並執行事件中。。。"); 29 foreach (var item in eventStort) 30 { 31 object objEventType = null; 32 object objEventMethodName = null; 33 object objEventMethodParamaterTypes = null; 34 object objEventArgs = null; 35 item.TryGetValue("eventType", out objEventType); 36 item.TryGetValue("eventMethodName", out objEventMethodName); 37 38 item.TryGetValue("eventMethodParamaterTypes", out objEventMethodParamaterTypes);//如為JSon格式還需反序列化成原來對象 39 item.TryGetValue("eventArgs", out objEventArgs);//如為JSon格式還需反序列化成原來對象 40 41 var delegator = CreateDelegator<DomainEventHandler>(objEventType.ToString(),objEventMethodName.ToString(),objEventMethodParamaterTypes as String[]); 42 var eventType = Type.GetType(objEventType.ToString()); //獲得委托調用者類型 43 var target = eventType.Assembly.CreateInstance(eventType.FullName); //實例化委托調用者 44 delegator(eventType, objEventArgs as BaseDomainEventArgs); 45 } 46 WriteLine("加載並執行事件完成"); 47 } 48 } 49 50 private void Persistence(DomainEventHandler DomainEvent, BaseDomainEventArgs eventArgs) 51 { 52 foreach (var item in HelloDomainEvent.GetInvocationList())//按照調用順序返回此多路廣播委托的調用列表。 53 { 54 var dic = new Dictionary<String, Object>(); 55 var eventType = item.Target.GetType().AssemblyQualifiedName;//獲取當前委托調用者的 System.Type 的程序集限定名,其中包括從中加載 System.Type 的程序集的名稱 56 var eventMethodName = item.Method.Name;//獲取委托表示方法的名稱 57 var eventMethodParamaters = item.Method.GetParameters();//獲取委托表示方法的參數 58 String[] eventMethodParamaterTypes = new String[eventMethodParamaters.Length];//委托表示方法的參數類型 59 var index = 0; 60 foreach (var paramater in eventMethodParamaters) 61 { 62 eventMethodParamaterTypes[index] = paramater.ParameterType.AssemblyQualifiedName;//獲取參數的System.Type 的程序集限定名,其中包括從中加載 System.Type 的程序集的名稱 63 index++; 64 } 65 dic.Add("eventType", eventType); 66 dic.Add("eventMethodName", eventMethodName); 67 dic.Add("eventMethodParamaterTypes", eventMethodParamaterTypes);//可轉為JSon格式保存 68 dic.Add("eventArgs", eventArgs);//可轉為JSon格式保存 69 eventStort.Add(dic); 70 } 71 } 72 73 private TDelegator CreateDelegator<TDelegator>(String strEventType, String eventMethodName, String[] strEventMethodParameterTypes) 74 { 75 var eventType = Type.GetType(strEventType); //獲得委托調用者類型 76 var target = eventType.Assembly.CreateInstance(eventType.FullName); //實例化委托調用者 77 var targetConstant = Expression.Constant(target, eventType); //創建委托調用常量表達式 78 79 ParameterExpression[] arguments = new ParameterExpression[strEventMethodParameterTypes.Length];//創建參數表達式數組 80 81 var index = 0; 82 foreach (var item in strEventMethodParameterTypes) 83 { 84 arguments[index] = Expression.Parameter(Type.GetType(strEventMethodParameterTypes[index]));//創建參數表達式,並將其賦值給數表達式數組 85 index++; 86 } 87 88 var methodCallExp = Expression.Call(targetConstant, eventType.GetMethod(eventMethodName), arguments);//創建一個表示調用帶參數的方法的MethodCallExpression。 89 //Expression.Lambda<TDelegator>(methodCallExp, arguments) 返回以表達式目錄樹的形式將強類型 lambda 表達式表示為數據結構的 Expression<TDelegate> 90 //Expression<TDelegate>.Compile() 將表達式樹描述的 lambda 表達式編譯為可執行代碼,並生成表示該 lambda 表達式的委托 91 return Expression.Lambda<TDelegator>(methodCallExp, arguments).Compile(); 92 } 93 }
/// <summary> /// 領域事件參數 /// </summary> public abstract class BaseDomainEventArgs: EventArgs { }
1 /// <summary> 2 /// 領域事件處理 3 /// </summary> 4 public abstract class BaseDomainEventHandler 5 { 6 public abstract void Handler(object sender, BaseDomainEventArgs eventArgs); 7 }
public class SayEventArgs: BaseDomainEventArgs { private String message; public String Message { get { return message; } set { message = value.ToUpper(); } } }
public class ChinaSayHelloHandler : BaseDomainEventHandler { public override void Handler(object sender, BaseDomainEventArgs eventArgs) { SayEventArgs sayEventArgs = (SayEventArgs)eventArgs; Console.WriteLine("{0}:中國說你好", sayEventArgs.Message); } } public class EnglishSayHelloHandler : BaseDomainEventHandler { public override void Handler(object sender, BaseDomainEventArgs eventArgs) { SayEventArgs sayEventArgs = (SayEventArgs)eventArgs; Console.WriteLine("{0}:English Say Hello", sayEventArgs.Message); } } public class ChinaSayByeByeHandler : BaseDomainEventHandler { public override void Handler(object sender, BaseDomainEventArgs eventArgs) { SayEventArgs sayEventArgs = (SayEventArgs)eventArgs; Console.WriteLine("{0}:中國說再見", sayEventArgs.Message); } } public class EnglishSyeByeBayHandler : BaseDomainEventHandler { public override void Handler(object sender, BaseDomainEventArgs eventArgs) { SayEventArgs sayEventArgs = (SayEventArgs)eventArgs; Console.WriteLine("{0}:English Say Bye Bye", sayEventArgs.Message); } }
執行結果:
將委托持久化及利用表達式樹從持久化庫還原委托