首页 > 代码库 > 将委托持久化及利用表达式树从持久化库还原委托
将委托持久化及利用表达式树从持久化库还原委托
在领域事件中,有时为了数据的一致性,需要先将事件持久化,然后在读取数据时还原并执行事件保证数据一致。
持久化委托时,我们需要持久化委托的类型、方法名称和方法参数类型。
如申明一个委托:
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); } }
执行结果:
将委托持久化及利用表达式树从持久化库还原委托
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。