zoukankan      html  css  js  c++  java
  • Emit生成特定接口的类

    参考 动态生成类

    http://www w2bc com/Article/44799

    http://www.cnblogs.com/yingql/archive/2009/03/24/1420914.html

    http://www.cnblogs.com/BangQ/archive/2011/07/19/2110301.html?spm=5176.100239.0.0.kAe2my

    http://www.cnblogs.com/yuming1983/p/3701540.html

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Reflection;
    using System.Reflection.Emit;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ConsoleApplication1
    {
    
        public interface IGetData
        {
            void GetData(string name);
        }
    
        public class GetDataFromDb : IGetData
        {
            public void GetData(string name)
            {
                Console.WriteLine( "Hello " + name);
            }
        }
    
        public class DynamicProxyBuilder
        {
            private static AssemblyBuilder DynamicAssembly;
            private static ModuleBuilder ModuleBuilder;
    
            private static Dictionary<string, Type> TypeList = new Dictionary<string, Type>();
            public static TTargetInterface GetProxyObject<TTargetInterface, TOriginalClass>() where TTargetInterface :class where TOriginalClass : TTargetInterface
            {
                Type target = typeof(TTargetInterface);
                Type baseType = typeof(TOriginalClass);
                CheckParams(target, baseType);
                Type proxyType = AutoGenerateProxyClass(target, baseType);
                var baseInstance = Activator.CreateInstance(baseType);
    
                return Activator.CreateInstance(proxyType, baseInstance ) as TTargetInterface;
            }
    
            private static Type AutoGenerateProxyClass(Type target, Type baseType)
            {
                var proxyClassName = baseType.FullName + "Proxy";
                if (!TypeList.ContainsKey(proxyClassName))
                {
                    var module = GetDynamicModule();
                    var typeBuilder = module.DefineType(proxyClassName, 
                        System.Reflection.TypeAttributes.Public | System.Reflection.TypeAttributes.Class,
                        typeof(System.Object), new Type[] { target });
    
                    var fieldBuilder = typeBuilder.DefineField("OriginalObj", target, System.Reflection.FieldAttributes.Public);
                    CreateConstructorFunctionForType(baseType, typeBuilder, fieldBuilder);
                    foreach (var methodInfo in target.GetMethods())
                    {
                        CreateMethodForType(baseType, typeBuilder, methodInfo, fieldBuilder);
                    }
    
                    TypeList.Add(proxyClassName, typeBuilder.CreateType());
                }
    
                return TypeList[proxyClassName];
            }
    
            private static void CreateConstructorFunctionForType(Type baseType, TypeBuilder typeBuilder, FieldBuilder fieldBuilder)
            {
                var objType = typeof(object);
                ConstructorInfo objCtor = objType.GetConstructor(new Type[0]);
                ConstructorBuilder cb = typeBuilder.DefineConstructor(MethodAttributes.Public, 
                    CallingConventions.Standard, new Type[] { baseType });
                ILGenerator ilGenerator = cb.GetILGenerator();
                ilGenerator.Emit(OpCodes.Ldarg_0);
                //先构建object的构造函数
                ilGenerator.Emit(OpCodes.Call, objCtor);
                ilGenerator.Emit(OpCodes.Ldarg_0);
                ilGenerator.Emit(OpCodes.Ldarg_1);
                //将本类的构建函数的参数赋值给本类的字段
                ilGenerator.Emit(OpCodes.Stfld, fieldBuilder);
                ilGenerator.Emit(OpCodes.Ret);
            }
    
            private static void CreateMethodForType(Type baseType, TypeBuilder typeBuilder, MethodInfo method, FieldBuilder fieldBuilder)
            {
                var parameterInfos = method.GetParameters();
                var paramTypes = new Type[parameterInfos.Length];
                for (int i = 0; i < parameterInfos.Length; i++)
                {
                    paramTypes[i] = parameterInfos[i].ParameterType;
                }
                //准备好真正要调用的方法
                var targetMethod = baseType.GetMethod(method.Name, paramTypes);
                //创建代理方法,使用接口中相应方法的信息,并去掉期抽象方法属性
                var methodBuilder = typeBuilder.DefineMethod(method.Name, method.Attributes & (~MethodAttributes.Abstract), 
                    method.CallingConvention
                    , method.ReturnType, paramTypes);
    
                var il = methodBuilder.GetILGenerator();
                il.EmitWriteLine("I am Proxyer");
                //开始向栈中压参数,
                //第1个参数 当前是this指针
                il.Emit(OpCodes.Ldarg_0);
                //压入当前引用的字段值 相当于 this.
                il.Emit(OpCodes.Ldfld, fieldBuilder);
                for (int i = 1; i <= parameterInfos.Length; i++)
                {
                    if (i == 0)
                    {
    
                    }
                    else if (i == 1)
                    {
                        il.Emit(OpCodes.Ldarg_1);
                    }
                    else if (i == 2)
                    {
                        il.Emit(OpCodes.Ldarg_2);
                    }
                    else if (i == 3)
                    {
                        il.Emit(OpCodes.Ldarg_3);
                    }
                    else
                    {
                        il.Emit(OpCodes.Ldarg_S);
                    }
                }
    
                il.Emit(OpCodes.Callvirt, targetMethod);
                il.EmitWriteLine("I done it!Bye!!");
                il.Emit(OpCodes.Ret);
    
            }
    
            private static ModuleBuilder GetDynamicModule()
            {
                if (DynamicProxyBuilder.DynamicAssembly == null)
                {
                    DynamicProxyBuilder.DynamicAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("DynamicAssembly"), 
                        AssemblyBuilderAccess.Run);
                    DynamicProxyBuilder.ModuleBuilder = DynamicProxyBuilder.DynamicAssembly.DefineDynamicModule("MainModule");
                }
    
                return DynamicProxyBuilder.ModuleBuilder;
            }
    
            private static void CheckParams(Type targetType, Type baseType)
            {
                if (!targetType.IsInterface)
                    throw new Exception("模板参数必须是接口");            
            }
        }
    
        public class Program
        {
            static void Main(string[] args)
            {
                var instance = DynamicProxyBuilder.GetProxyObject<IGetData, GetDataFromDb>();
                instance.GetData("Aven");
                Console.Read();
             }
         }
    }
  • 相关阅读:
    MongoDB对比关系型数据库
    Swagger 打开时自动折叠
    更改Linux定时任务crontab启动基目录
    linux系统/etc/init.d目录下的开机自启脚本
    vue 中新窗口打开vue页面 (this.$router.resolve)
    树莓派4B如何手动固定IP地址
    树莓派无显示器设置WiFi、开启ssh、开启VNC
    递归
    学习-HTML5
    只是为了表示我还有在敲代码
  • 原文地址:https://www.cnblogs.com/zhshlimi/p/6822989.html
Copyright © 2011-2022 走看看