using System;
using System.Net;using System.Windows;using System.Windows.Controls;using System.Windows.Documents;using System.Windows.Ink;using System.Windows.Input;using System.Windows.Media;using System.Windows.Media.Animation;using System.Windows.Shapes;using System.Reflection;using System.Reflection.Emit;namespace EmitHandler
{ public class Example { /// <summary> /// 使用反射将委托挂钩 /// </summary> /// <param name="outputBlock"></param> public static void Demo(System.Windows.Controls.TextBlock outputBlock) { // 获取某一未知对象,或者创建在您已加载的程序集中找到的类型的对象。 // 为使示例简单,使用的对象是为示例的输出提供的 TextBlock; // 但是,TextBlock 存储为 Object 类型,以保持对该对象或其来自的程序集一无所知的状态 object obj = outputBlock;// 获取表示该事件的 EventInfo 对象,并使用 EventHandlerType 属性来获取用于处理事件的委托类型。
// 在下面的代码中,获取了 MouseLeftButtonUp 事件的 EventInfo。 // 此示例按名称查找事件,但可以使用 Type.GetEvents 方法来查看存在哪些事件 //foreach(EventInfo ei in outputBlock.GetType().GetEvents()) //{ // outputBlock.Text += ei.Name+"\n"; //}//Type opb = typeof(TextBlock);
//foreach (MethodInfo ei in opb.GetMethods())
//{ // //if (ei.Name.StartsWith("g")) // outputBlock.Text += ei.Name + "\n"; //}EventInfo evMouseUp = outputBlock.GetType().GetEvent("MouseLeftButtonUp"); Type tEenType = evMouseUp.EventHandlerType;
// If you already have a method with the correct signature,
// you can simply get a MethodInfo for it. // MethodInfo miHandler = typeof(Example).GetMethod("LuckyHandler", BindingFlags.NonPublic | BindingFlags.Static); // 创建委托实例. Delegate d = Delegate.CreateDelegate(tEenType, miHandler);//获取 add 访问器方法,并调用该方法以将事件挂钩。
//所有事件都具有一个 add 访问器或 remove 访问器,这些访问器被高级语言的语法隐藏。 //例如,C# 使用 += 运算符将事件挂钩,而 Visual Basic 则使用 AddHandler 语句。 //下面的代码获取 MouseLeftButtonUp 事件的 add 访问器并以后期绑定方式调用它,并在委托实例中传递。 //参数必须作为数组传递 MethodInfo miAddHandler = evMouseUp.GetAddMethod(); object[] addHandlerArgs = { d }; miAddHandler.Invoke(obj, addHandlerArgs); //outputBlock.Text += "Click here to invoke the two delegates.\n"; // 使用轻量动态方法和反射发出可在运行时生成事件处理程序方法。 // 若要构造事件处理程序,您需要知道返回类型和委托的参数类型。 // 可以通过检查委托的 Invoke 方法来获取这些类型。下 // 面的代码使用 GetDelegateReturnType 和 GetDelegateParameterTypes 方法通过反射获取此信息。 Type returnType = GetDelegateReturnType(tEenType); if (returnType != typeof(void)) { throw new InvalidOperationException("Delegate has a return type."); }DynamicMethod handler =
new DynamicMethod("", null, GetDelegateParameterTypes(tEenType));// 生成方法体。
//此方法加载字符串、 //调用带有单个字符串的 Show 方法重载、 //从堆栈弹出返回值(因为处理程序没有返回类型)并返回这些值. ILGenerator ilgen = handler.GetILGenerator();Type[] showParameters = { typeof(string) };
MethodInfo miShow = typeof(System.Windows.MessageBox).GetMethod("Show", showParameters);//推送对元数据中存储的字符串的新对象引用
ilgen.Emit(OpCodes.Ldstr, "This event handler was constructed at run time."); //调用方法 ilgen.Emit(OpCodes.Call, miShow); //出栈 ilgen.Emit(OpCodes.Pop); //返回 ilgen.Emit(OpCodes.Ret); Delegate dEmitted = handler.CreateDelegate(tEenType); evMouseUp.AddEventHandler(obj, dEmitted);// Clicking on the TextBlock now causes the two delegates to
// be invoked. // outputBlock.Text += "Click here to invoke the two delegates.\n"; }private static void LuckyHandler(object sender, EventArgs e)
{ System.Windows.MessageBox.Show( "This event handler just happened to be lying around."); }private static Type[] GetDelegateParameterTypes(Type d)
{ if (d.BaseType != typeof(MulticastDelegate)) { throw new InvalidOperationException("Not a delegate."); }MethodInfo invoke = d.GetMethod("Invoke");
if (invoke == null) { throw new InvalidOperationException("Not a delegate."); }ParameterInfo[] parameters = invoke.GetParameters();
Type[] typeParameters = new Type[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { typeParameters[i] = parameters[i].ParameterType; }return typeParameters;
} private static Type GetDelegateReturnType(Type d) { if (d.BaseType != typeof(MulticastDelegate)) { throw new InvalidOperationException("Not a delegate."); }MethodInfo invoke = d.GetMethod("Invoke");
if (invoke == null) { throw new InvalidOperationException("Not a delegate."); }return invoke.ReturnType;
}}
}