http://blog.csdn.net/KAMILLE/archive/2008/01/15/2045459.aspx
几个月前写的版本,使用反射性能不够好,而且使用不够方便。这个版本使用接口定义,性能接近系统的DllImport。支持.net1.0。(如果是.net2.0可以使用Delegate转换函数指针)
- using System;
- using System.Reflection;
- using System.Reflection.Emit;
- using System.Runtime.InteropServices;
- public class DllImporter
- {
- [DllImport("Kernel32.dll")]
- static extern IntPtr LoadLibrary(string lpFileName);
- [DllImport("Kernel32.dll")]
- static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
- [DllImport("Kernel32.dll")]
- static extern bool FreeLibrary(IntPtr hModule);
- public static object Create(string dllFile, Type interfaceType)
- {
- //检查参数
- if (dllFile == null) throw new ArgumentNullException();
- if (interfaceType.IsInterface == false) throw new ArgumentException();
- //函数指针( 这里其实要释放的,偷懒:P )
- IntPtr libPtr = LoadLibrary(dllFile);
- if (libPtr == IntPtr.Zero) throw new DllNotFoundException(dllFile);
- //创建模块
- AssemblyName assemblyName = new AssemblyName();
- assemblyName.Name = "DynamicAssembly";
- AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
- ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("DynamicModule");
- //创建类型
- TypeBuilder type = moduleBuilder.DefineType("DynamicType", TypeAttributes.Class, typeof(Object), new Type[] { interfaceType });
- //创建方法
- MethodInfo[] methods = interfaceType.GetMethods();
- foreach (MethodInfo method in methods)
- {
- IntPtr procPtr = GetProcAddress(libPtr, method.Name);
- if (procPtr == IntPtr.Zero) throw new EntryPointNotFoundException(method.Name);
- MethodAttributes attribute = method.Attributes & ~(MethodAttributes.Abstract);
- Type returnType = method.ReturnType;
- ParameterInfo[] parameters = method.GetParameters();
- Type[] argumentsType = new Type[parameters.Length];
- for (int i = 0; i < parameters.Length; i++)
- argumentsType[i] = parameters[i].ParameterType;
- MethodBuilder methodBuilder = type.DefineMethod(method.Name, attribute, returnType, argumentsType);
- ILGenerator ilGen = methodBuilder.GetILGenerator();
- for (int i = 0; i < argumentsType.Length; i++)
- ilGen.Emit(OpCodes.Ldarg, i + 1); //注意这里从1开始,0是this
- if (IntPtr.Size == 4) ilGen.Emit(OpCodes.Ldc_I4, (int)procPtr);
- else if (IntPtr.Size == 8) ilGen.Emit(OpCodes.Ldc_I8, (long)procPtr);
- ilGen.EmitCalli(OpCodes.Calli, CallingConvention.StdCall, returnType, argumentsType);
- ilGen.Emit(OpCodes.Ret);
- //显式接口方法需要定义 Override,而普通实现不需要。
- type.DefineMethodOverride(methodBuilder, method);
- }
- //FreeLibrary(libPtr);
- //创建类型
- return Activator.CreateInstance(type.CreateType());
- }
- }
- public class Test
- {
- public interface Iuser32
- {
- IntPtr GetDC(IntPtr hWnd);
- int ReleaseDC(IntPtr hWnd, IntPtr hDC);
- }
- public interface Igdi32
- {
- bool TextOutA(IntPtr hdc, int nXStart, int nYStart, string lpString, int cbString);
- uint SetTextColor(IntPtr hdc, uint crColor);
- }
- static void Main(string[] args)
- {
- Iuser32 user32 = DllImporter.Create("user32.dll", typeof(Iuser32)) as Iuser32;
- Igdi32 gdi32 = DllImporter.Create("gdi32.dll", typeof(Igdi32)) as Igdi32;
- IntPtr dc = user32.GetDC(IntPtr.Zero);
- gdi32.SetTextColor(dc, 0xff);
- int x = 0; int y = 0; int sx = 1; int sy = 1;
- for (int i = 0; i < 10000; i++)
- {
- if (x > 1024 || x < 0) sx *= -1;
- if (y > 768 || y < 0) sy *= -1;
- x += sx;
- y += sy;
- gdi32.TextOutA(dc, x, y, "hello", 5);
- System.Threading.Thread.Sleep(5);
- }
- user32.ReleaseDC(IntPtr.Zero, dc);
- }
- }