Emit进阶 创建自定义委托Delegate
来源:互联网 发布:无硬件基础学linux 编辑:程序博客网 时间:2024/05/16 00:30
随着上次对Emit的研究,对MSIL和Emit有了进一步了解,不过为了更好地实现Aop需要自己定义委托,但是Emit定义委托就没有类这么容易理解,在多次对照IL代码后,终于成功的实现了自定义委托Delegate。
首先来看看一般的委托定义方法。
public delegate string MyDelegate(string message);
MSDN定义,委托是一种数据结构,它引用静态方法或引用类实例及该类的实例方法。
但是委托的本质是一个由系统自动生成的类,我们首先看看IL里面的MyDelegate的结构
可以看到实际上MyDelegate是继承自MulticastDelegate的类
MSIL表示方式如下:
.class public auto ansi sealed EmitDemo.DelegateDemo.MyDelegate extends [mscorlib]System.MulticastDelegate{} // end of class EmitDemo.DelegateDemo.MyDelegate.method public hidebysig specialname rtspecialname instance void .ctor(object 'object', native int 'method') runtime managed{} // end of method MyDelegate::.ctor.method public hidebysig newslot virtual instance string Invoke(string message) runtime managed{} // end of method MyDelegate::Invoke
不考虑异步调用,实际的类大概是这样的表示形式,但是C#并不允许直接继承MulticastDelegate,所以编译是无法通过的。
public class MyDelegate:MulticastDelegate { public MyDelegate(object target,IntPtr method) :base(target,method) { } public override string Invoke(string message){} }
接下来仿照这个定义来实现委托类
首先是moduleBuilder 经常使用Emit的应该很熟悉了
string name = "MyDelegateDemo"; string fileName = name + ".dll"; var assemblyName = new AssemblyName(name); var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave); var moduleBuilder = assemblyBuilder.DefineDynamicModule(name, fileName);
接下来是定义类,要点是修饰参数要一致,基类是MulticastDelegate
//public auto ansi sealed var delegateBuilder = moduleBuilder.DefineType("MyDelegate", TypeAttributes.Public | TypeAttributes.AutoLayout | TypeAttributes.AnsiClass | TypeAttributes.Sealed, typeof(MulticastDelegate));
在设置构造函数,修饰参数也要一致,函数参数为object和IntPtr
最重要的是最后一句设置方法实现标志为runtime
// .method public hidebysig specialname rtspecialname // instance void .ctor(object 'object', // native int 'method') runtime managed //{ //} // end of method MyDelegate::.ctor var constructorBuilder = delegateBuilder.DefineConstructor( MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, CallingConventions.Standard, new[] { typeof(object), typeof(IntPtr) } ); constructorBuilder.SetImplementationFlags(MethodImplAttributes.Runtime);
然后是定义方法Invoke,这里定义的返回值和参数都是string 可以根据需要调整。
同样修饰要一致,最后也要设置方法实现标志为Runtime
// .method public hidebysig newslot virtual // instance string Invoke(string message) runtime managed //{ //} // end of method MyDelegate::Invoke var resultType = typeof(string); var paramTypes = new[] { typeof(string) }; var methodBuilder = delegateBuilder.DefineMethod("Invoke", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual, CallingConventions.Standard, resultType, paramTypes); methodBuilder.SetImplementationFlags(MethodImplAttributes.Runtime);
最后创建类型,好了,定义完成了。
var delegateType = delegateBuilder.CreateType();
接下来就需要调用测试一下了。
注意不能用Activator.CreateInstance()来初始化代理而是Delegate.CreateDelegate。
public class MyClass { public string MyMethod(string message) { Console.WriteLine(message); return message; } }
调用
MyClass myClass = new MyClass(); var myDelegate = Delegate.CreateDelegate(delegateType, myClass, "MyMethod"); myDelegate.DynamicInvoke("Hello World!");
public class ClassDelagate { public ClassDelagate() { string name = "MyDelegateDemo"; string fileName = name + ".dll"; var assemblyName = new AssemblyName(name); var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave); var moduleBuilder = assemblyBuilder.DefineDynamicModule(name, fileName); var delegateBuilder = moduleBuilder.DefineType("MyDelegate", TypeAttributes.Public | TypeAttributes.AutoLayout | TypeAttributes.AnsiClass | TypeAttributes.Sealed, typeof(MulticastDelegate)); var constructorBuilder = delegateBuilder.DefineConstructor(MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, CallingConventions.Standard, new[] { typeof(object), typeof(IntPtr) }); constructorBuilder.SetImplementationFlags(MethodImplAttributes.Runtime); var resultType = typeof(string); var paramTypes = new[] { typeof(string) }; var methodBuilder = delegateBuilder.DefineMethod("Invoke", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual, CallingConventions.Standard, resultType, paramTypes); methodBuilder.SetImplementationFlags(MethodImplAttributes.Runtime); var delegateType = delegateBuilder.CreateType(); MyClass myClass = new MyClass(); var myDelegate = Delegate.CreateDelegate(delegateType, myClass, "MyMethod"); myDelegate.DynamicInvoke("Hello World!"); } } public class MyClass { public string MyMethod(string message) { Console.WriteLine(message); return message; } }
结果 Hello World!
OK 成功了。
- Emit进阶 创建自定义委托Delegate
- Emit创建常见元素—自定义类型
- 委托(delegate)在自定义控件的应用
- 委托(Delegate)
- 委托(Delegate)
- delegate委托
- 委托(delegate)
- Delegate 委托
- delegate 委托
- 委托:delegate
- 委托 delegate
- 委托(delegate)
- 委托,delegate
- delegate-委托
- 委托 delegate
- delegate委托
- Delegate委托
- 委托 delegate(System.Delegate)
- 软件测试工作内容
- XPathDocument 读取带命名空间的节点
- csdn管理员脑子怎么了?不让我把文章发布到首页???
- photoshop使用小技巧
- 如何在C#.net中自定义和使用特性
- Emit进阶 创建自定义委托Delegate
- ThreadLocal与synchronized
- 机载激光雷达测量技术理论与方法读书笔记(2)机载激光雷达测量技术的发展及应用
- 使用Exchange邮件跟踪
- uml大牛博客链接
- Excel自动化程序发生“Micosoft Excel已停止工作”的问题解决
- c#的DateTime.Now函数详解
- ASP.NET MVC3的伪静态实现
- 将Tomcat加入windows系统服务