首页 > 代码库 > Emit生成特定接口的类

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

 

Emit生成特定接口的类