emit动态生成的类不能用

瓶中小河 2023-05-10 13:58:39

public static Type CreateProxyType()
        {
            //获得当前的程序域
            AppDomain currentDomain = Thread.GetDomain();
            //创建这个类的程序集
            AssemblyName assemblyName = new AssemblyName("ProxyServiceClass");
            AssemblyBuilder assemblyBuilder = currentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
            //创建模块
            ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("ProxyServiceClass", "ProxyServiceClass.dll");

            //创建类型:传入父类,接口参数
            TypeBuilder typeBuilder = moduleBuilder.DefineType("ProxyServiceClass", TypeAttributes.Public, typeof(ServiceClass));

            var field = typeBuilder.DefineField("_interceptor", typeof(IInterceptor), FieldAttributes.Private);

            MethodInfo befMet = typeof(ProxyInterceptor).GetMethod("InterceptBef");
            MethodInfo aftMet = typeof(ProxyInterceptor).GetMethod("InterceptAft");

            var consmt = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, Type.EmptyTypes);

            ConstructorInfo constructorInfo = typeof(ProxyInterceptor).GetConstructor(Type.EmptyTypes);
            ConstructorInfo baseConst = typeof(ServiceClass).GetConstructor(Type.EmptyTypes);

            var ilconst = consmt.GetILGenerator();
            ilconst.DeclareLocal(typeof(ProxyInterceptor));

            ilconst.Emit(OpCodes.Ldarg_0);
            ilconst.Emit(OpCodes.Call, baseConst);
            ilconst.Emit(OpCodes.Newobj, constructorInfo);
            ilconst.Emit(OpCodes.Stloc_0);
            ilconst.Emit(OpCodes.Ldarg_0);
            ilconst.Emit(OpCodes.Ldloc_0);
            ilconst.Emit(OpCodes.Stfld, field);
            ilconst.Emit(OpCodes.Pop);
            ilconst.Emit(OpCodes.Ret);

            MethodInfo[] methods = typeof(ServiceClass).GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
            foreach (var item in methods)
            {
                if (!item.IsVirtual)
                    continue;

                var parTypes = item.GetParameters().Select(x => x.ParameterType).ToArray();
                MethodBuilder mb = typeBuilder.DefineMethod(item.Name, MethodAttributes.Public | MethodAttributes.Virtual, item.ReturnType, parTypes ?? Type.EmptyTypes);
                ILGenerator il = mb.GetILGenerator();

                // 声明方法内部的局部变量,返回参数
                if (item.ReturnType != typeof(void))
                    il.DeclareLocal(item.ReturnType);
                foreach (var parType in parTypes)
                    il.DeclareLocal(parType);

                il.Emit(OpCodes.Nop);
                // this._interceptor.InterceptBef();
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldfld, field);
                il.EmitCall(OpCodes.Callvirt, befMet, Type.EmptyTypes);

                // base.xxx(proxy function)
                il.Emit(OpCodes.Ldarg_0);
                for (int i = 0; i < parTypes.Length; i++)
                {
                    il.Emit(OpCodes.Ldarg, i + 1);
                }
                il.EmitCall(OpCodes.Call, item, parTypes);

                if (item.ReturnType != typeof(void))
                    il.Emit(OpCodes.Stloc_0);

                // this._interceptor.InterceptAft();
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldfld, field);
                il.EmitCall(OpCodes.Callvirt, aftMet, Type.EmptyTypes);

                if (item.ReturnType != typeof(void))
                    il.Emit(OpCodes.Ldloc_0);
                else
                    il.Emit(OpCodes.Pop);
                il.Emit(OpCodes.Ret);
            }

            Type retType = typeBuilder.CreateType();
            assemblyBuilder.Save("ProxyServiceClass.dll");

            return retType;
        }

public class ServiceClass
    {
        public virtual string GetDataById(int id)
        {
            return $"GetDataById return {id}";
        }

        public virtual void UpdateById(int id)
        {
        }

        public virtual string SelectById()
        {
            return "SelectById";
        }

        public virtual void DeleteById()
        {
        }
    }

// 想生成的类

public class ProxyServiceClass2 : ServiceClass
    {
        private IInterceptor _interceptor;

        public ProxyServiceClass2()
        {
            this._interceptor = new ProxyInterceptor();
        }
        public override string GetDataById(int id)
        {
            string resultStr;
            _interceptor.InterceptBef();
            resultStr = base.GetDataById(id);
            _interceptor.InterceptAft();
            return resultStr;
        }

        public override void UpdateById(int id)
        {
            _interceptor.InterceptBef();
            base.UpdateById(id);
            _interceptor.InterceptAft();
        }

        public override string SelectById()
        {
            string resultStr;
            _interceptor.InterceptBef();
            resultStr = base.SelectById();
            _interceptor.InterceptAft();
            return resultStr;
        }

        public override void DeleteById()
        {
            _interceptor.InterceptBef();
            base.DeleteById();
            _interceptor.InterceptAft();
        }
    }

我看dll能正常生成,反编译后的代码也有9成相似,但这种类型不能 Activator.CreateInstance(type) 生成正常的实例,想问问大佬问题出在哪

 

...全文
99 2 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
CSDN-Ada助手 2023-05-10
精选
  • 打赏
  • 举报
回复
您的问题已经帮您同步至问答, 链接: https://ask.csdn.net/questions/7941736, 请您保持关注, 如果回答有帮助解决此问题, 麻烦您动动小手给相关的回答点赞, Ada会在评论区为您更新结题状态
瓶中小河 2023-05-10
  • 打赏
  • 举报
回复

img


这是反编译后的样子,最后一个方法看注释不知道哪里写的有问题。头大

111,102

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧