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();
}}
问题可能出在创建类型时使用了"_"作为字段名的前缀,导致生成的属性名称包含了下划线。可以尝试将所有的"_"前缀改为其他字符。
在Java中,命名规范不鼓励使用""作为字段名的前缀。可以通过重构代码,将所有的""前缀改为其他字符,比如通过camelCase或者PascalCase的方式来命名。例如,将"_firstName"改为"firstName"或者"FirstName"。
具体做法:
打开Java代码文件,在编辑器中使用“查找并替换”功能,找到所有以""开头的字段名。比如,用Eclipse编辑器的“查找”功能,在搜索框中输入“[a-z]”,按下回车。
选中所有被找到的字段名,将它们改为camelCase或者PascalCase格式的字段名,比如“firstName”或者“FirstName”。
在修改后的代码中测试程序,确保其正常运行。