Delegate如何进行类型转换?
我们知道对于两个不具有继承关系的两个类型,如果没有为它们定义转换器,两这之间的类型转换是不允许的,Delegate也是如此。但是有时候我们却希望“兼容”的两种Delegate类型能够进行转换,比较典型的就是表示事件的Delegate。.NET Framework为我们定义了类型EventHandler来表示事件,但是却没有规定事件的Delegate类型是EventHandler的子类。原则上讲,事件可以是任意类型的Delegate,但是我们使用的事件一般具有如下两个共同点:
如果事件的类型不是EventHandler的子类,我们是不可以将一个EventHandler对象对事件进行注册的。如果我们能够将EventHandler对象转换成事件对应的类型,那么就可以到达这样的目的:将同一个EventHandler注册给任意的事件。我们举个简单的例子,假设我们具有这样一个需求:对于指定的某个对象,需要在它每一个事件触发的时候我们进行响应的日志记录。具体实现如下面的代码所示,具体的日志记录实现在Log方法中,RegisterEventHandler<T>方法中我们通过反射的方式获取类型T中定义的所有Event,并将指定的EventHandler针对这些事件进行注册。由于类型可能不一致,我们通过调用自定义的EventHandlerConverter的静态方法Convert进行类型转换。[源代码从这里下载] 1: static void RegisterEventHandler<T>(T target,EventHandler eventHandler) 3: EventInfo[] events = typeof(T).GetEvents();
5: { 7: } 2: { }4: { }6: { }8: delegate void BarEventHandler(object sender,BarEventArgs e);10: void QuxEventHandler( 11:?13: { 实现在EventHandlerConverter的静态方法Convert方法中的EventHandler与兼容Delegate类型之间的转换是通过“Emit”的机制实现,具体的实现逻辑如下面的代码片断所示。IsValidEventHandler方法用于验证指定的类型是否与EventHandler兼容(按照上面提及的标准进行验证),在Convert方法中我们通过Emit的方式创建了一个DynamicMethod 对象,并最终调用CreateDelegate方法将指定的Delegate对象转换成目标Delegate类型。泛型方法Convert<TDelegate>以强类型的方式指定转换的目标类型。 bool IsValidEventHandler(Type eventHandlerType,1)">out ParameterInfo[] parameters)
6: if (!typeof(Delegate).IsAssignableFrom(eventHandlerType)) 8: parameters = new ParameterInfo[0];
10: } 13: if (invokeMethod.ReturnType != typeof(void)) 15: parameters = new ParameterInfo[0];
17: } 19: if (parameters.Length != 2 || parameters[0].ParameterType != object)) 21: 22: }
24: { 27: true;
29:? 31: { 33: Guard.ArgumentNotNull(eventHandlerType,1)" id="lnum34"> 34:? 36: if (!IsValidEventHandler(eventHandlerType,1)">out destinationParameters))
38: throw new InvalidOperationException(); 40:? 42: { 44: } 46: ParameterInfo[] sourceParameters; 48: { 50: } 52: paramTypes[0] = eventHandler.GetType(); 54: { 56: } 58: MethodInfo invoker = paramTypes[0].GetMethod( 59: ILGenerator il = method.GetILGenerator();
61: il.Emit(OpCodes.Ldarg_1); 63: if (!sourceParameters[1].ParameterType.IsAssignableFrom(destinationParameters[1].ParameterType))
65: il.Emit(OpCodes.Castclass,sourceParameters[1].ParameterType); 67: il.Emit(OpCodes.Call,invoker); 69: return method.CreateDelegate(eventHandlerType,eventHandler);
71:? 73: { 75: } 相关内容
推荐文章
站长推荐
热点阅读
|