• c# emit 实现类的代理


    using System;
    using System.Linq;
    using System.Reflection;
    using System.Reflection.Emit;
    
    namespace EmitCreateDynamicProxy
    {
        class Program
        {
            static void Main(string[] args)
            {
                var command = Proxy.Of<Command>();
                command.Execute();
    
                Console.ReadLine();
            }
        }
    
        public class Command
        {
            public virtual void Execute()
            {
    
                Console.WriteLine("Hello Kitty!");
    
            }
        }
    
     
    
        public class Interceptor
        {
            public object Invoke(object @object, string @method, object[] parameters)
            {
                Console.WriteLine(
                  string.Format(" before invoke [{0}]...", @method));
    
                var retObj = @object.GetType().GetMethod(@method).Invoke(@object, parameters);
    
                Console.WriteLine(
                  string.Format(" after invoke [{0}]...", @method));
    
                return retObj;
            }
        }
    
        public class Proxy
        {
            public static T Of<T>() 
            {
                string nameOfAssembly = typeof(T).Name + "ProxyAssembly";
                string nameOfModule = typeof(T).Name + "ProxyModule";
                string nameOfType = typeof(T).Name + "Proxy";
    
                var assemblyName = new AssemblyName(nameOfAssembly);
                var assembly = AppDomain.CurrentDomain
                  .DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
                var moduleBuilder = assembly.DefineDynamicModule(nameOfModule);
              
                var typeBuilder = moduleBuilder.DefineType(
                  nameOfType, TypeAttributes.Public,typeof(T));
    
                InjectInterceptor<T>(typeBuilder);
    
                var t = typeBuilder.CreateType();
    
                return (T)Activator.CreateInstance(t) ;
            }
    
            private static void InjectInterceptor<T>(TypeBuilder typeBuilder)
            {
                // ---- define fields ----
    
                var fieldInterceptor = typeBuilder.DefineField(
                  "_interceptor", typeof(Interceptor), FieldAttributes.Private);
    
                // ---- define costructors ----
    
                var constructorBuilder = typeBuilder.DefineConstructor(
                  MethodAttributes.Public, CallingConventions.Standard, null);
                var ilOfCtor = constructorBuilder.GetILGenerator();
    
                ilOfCtor.Emit(OpCodes.Ldarg_0);
                ilOfCtor.Emit(OpCodes.Newobj, typeof(Interceptor).GetConstructor(new Type[0]));
                ilOfCtor.Emit(OpCodes.Stfld, fieldInterceptor);
                ilOfCtor.Emit(OpCodes.Ret);
    
                // ---- define methods ----
    
                var methodsOfType = typeof(T).GetMethods(BindingFlags.Public | BindingFlags.Instance);
    
                for (var i = 0; i < methodsOfType.Length; i++)
                {
                    var method = methodsOfType[i];
                    var methodParameterTypes =
                      method.GetParameters().Select(p => p.ParameterType).ToArray();
    
                    var methodBuilder = typeBuilder.DefineMethod(
                      method.Name,
                      MethodAttributes.Public | MethodAttributes.Virtual,
                      CallingConventions.Standard,
                      method.ReturnType,
                      methodParameterTypes);
    
                    var ilOfMethod = methodBuilder.GetILGenerator();
                    ilOfMethod.Emit(OpCodes.Ldarg_0);
                    ilOfMethod.Emit(OpCodes.Ldfld, fieldInterceptor);
    
                    // create instance of T
                  ilOfMethod.Emit(OpCodes.Newobj, typeof(T).GetConstructor(new Type[0]));
                   ilOfMethod.Emit(OpCodes.Ldstr, method.Name);
    
                    // build the method parameters
                    if (methodParameterTypes == null)
                    {
                        ilOfMethod.Emit(OpCodes.Ldnull);
                    }
                    else
                    {
                        var parameters = ilOfMethod.DeclareLocal(typeof(object[]));
                        ilOfMethod.Emit(OpCodes.Ldc_I4, methodParameterTypes.Length);
                        ilOfMethod.Emit(OpCodes.Newarr, typeof(object));
                        ilOfMethod.Emit(OpCodes.Stloc, parameters);
    
                        for (var j = 0; j < methodParameterTypes.Length; j++)
                        {
                            ilOfMethod.Emit(OpCodes.Ldloc, parameters);
                            ilOfMethod.Emit(OpCodes.Ldc_I4, j);
                            ilOfMethod.Emit(OpCodes.Ldarg, j + 1);
                            ilOfMethod.Emit(OpCodes.Stelem_Ref);
                        }
                        ilOfMethod.Emit(OpCodes.Ldloc, parameters);
                    }
    
                    // call Invoke() method of Interceptor
                    ilOfMethod.Emit(OpCodes.Callvirt, typeof(Interceptor).GetMethod("Invoke"));
    
                    // pop the stack if return void
                    if (method.ReturnType == typeof(void))
                    {
                        ilOfMethod.Emit(OpCodes.Pop);
                    }
    
                    // complete
                    ilOfMethod.Emit(OpCodes.Ret);
                }
            }
        }
    }
  • 相关阅读:
    Stack
    js this理解
    js面向对象
    自执行函数
    原!struts安全漏洞,由2.3.37版本升级至2.5.22
    原!linux机器 配置自动scp脚本
    转!!记一次使用 Arthas 热更新线上代码
    mysql 修改大表字段,报错ERROR 1878 (HY000): Temporary file write failure. 用pt-online-schema-change
    转!!JAVA Future 模式与 Promise 模式
    转!!linux下详解shell中>/dev/null 2>&1
  • 原文地址:https://www.cnblogs.com/tiancai/p/8283185.html
Copyright © 2020-2023  润新知