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;
}
}
}