C# ILGenerator:如何生成函数<&燃气轮机;作为论据通过
我试图围绕由接口定义的服务创建一个代理包装器,以对服务的开发人员用户“隐藏”特定于客户端的调用代码 我已经能够生成包装器类本身的大部分内容,但现在正在努力为预先存在的客户机调用生成Func参数 示例TService有一个接口:C# ILGenerator:如何生成函数<&燃气轮机;作为论据通过,c#,wrapper,reflection.emit,emit,ilgenerator,C#,Wrapper,Reflection.emit,Emit,Ilgenerator,我试图围绕由接口定义的服务创建一个代理包装器,以对服务的开发人员用户“隐藏”特定于客户端的调用代码 我已经能够生成包装器类本身的大部分内容,但现在正在努力为预先存在的客户机调用生成Func参数 示例TService有一个接口: public interface ITestService { public Task ServiceMethodAsync(); public Task<TestDTO> ServiceMethodWithResultAsync(); }
public interface ITestService
{
public Task ServiceMethodAsync();
public Task<TestDTO> ServiceMethodWithResultAsync();
}
而首选的选择是,他们可以直接打电话:
var result = await service.ServiceMethodWithResultAsync(requestDTO);
因为这允许DI使用IService接口注入本地服务或my remote wrapper,开发人员不需要考虑它是远程服务还是本地服务
我目前让typebuilder生成所需的代码,以创建从客户机继承的包装类baseType
,并针对它定义所有接口方法,但当前将null作为Func操作传递
private static void DefineInterface(TypeBuilder typeBuilder, Type baseType, Type serviceInterfaceType)
{
foreach (MethodInfo serviceMethod in serviceInterfaceType.GetMethods())
{
ParameterInfo[] parameters = serviceMethod.GetParameters();
MethodBuilder methodBuilder = typeBuilder.DefineMethod(
serviceMethod.Name,
serviceMethod.Attributes ^ MethodAttributes.Abstract,
serviceMethod.CallingConvention,
serviceMethod.ReturnType,
serviceMethod.ReturnParameter.GetRequiredCustomModifiers(),
serviceMethod.ReturnParameter.GetOptionalCustomModifiers(),
parameters.Select(p => p.ParameterType).ToArray(),
parameters.Select(p => p.GetRequiredCustomModifiers()).ToArray(),
parameters.Select(p => p.GetOptionalCustomModifiers()).ToArray());
ILGenerator ilGenerator = methodBuilder.GetILGenerator();
MethodInfo callAsyncMethod = getCallAsyncMethod(baseType, serviceMethod);
ilGenerator.Emit(OpCodes.Ldarg_0); // Push "this"
ilGenerator.Emit(OpCodes.Ldnull); // Push Func<> argument
ilGenerator.Emit(OpCodes.Call, callAsyncMethod); // Call CallAsync on the base client
ilGenerator.Emit(OpCodes.Ret);
}
}
私有静态void DefineInterface(TypeBuilder、TypeBaseType、TypeServiceInterfaceType)
{
foreach(serviceInterfaceType.GetMethods()中的MethodInfo serviceMethod)
{
ParameterInfo[]parameters=serviceMethod.GetParameters();
MethodBuilder MethodBuilder=typeBuilder.DefineMethod(
serviceMethod.Name,
serviceMethod.Attributes^MethodAttributes.Abstract,
serviceMethod.CallingConvention,
serviceMethod.ReturnType,
serviceMethod.ReturnParameter.GetRequiredCustomModifiers(),
serviceMethod.ReturnParameter.GetOptionalCustomModifiers(),
parameters.Select(p=>p.ParameterType).ToArray(),
parameters.Select(p=>p.GetRequiredCustomModifiers()).ToArray(),
选择(p=>p.GetOptionalCustomModifiers()).ToArray();
ILGenerator ILGenerator=methodBuilder.GetILGenerator();
MethodInfo callAsyncMethod=getCallAsyncMethod(baseType,serviceMethod);
ilGenerator.Emit(操作码.Ldarg_0);//推送“this”
ilGenerator.Emit(OpCodes.Ldnull);//Push Func参数
ilGenerator.Emit(OpCodes.Call,callAsyncMethod);//在基本客户端上调用CallAsync
ilGenerator.Emit(操作码.Ret);
}
}
从这里开始,我有点纠结于如何准确地定义Funcservice=>service.ServiceMethodWithResultAsync(requestDTO)
包括requestDTO
参数,我期望/假设这些参数将出现在Ldarg\u 1
、Ldarg\u 2
中
非常感谢您的帮助。我对IL不是很坚定。我更喜欢使用ExpressionTrees来创建动态lambda函数,但这不能用于创建整个类。如果您像在IL中创建一样编写一个示例实现,可能会有所帮助。运行编译器并使用任何反编译器查看创建的内容。也许你会得到你需要的提示。
var result = await service.ServiceMethodWithResultAsync(requestDTO);
private static void DefineInterface(TypeBuilder typeBuilder, Type baseType, Type serviceInterfaceType)
{
foreach (MethodInfo serviceMethod in serviceInterfaceType.GetMethods())
{
ParameterInfo[] parameters = serviceMethod.GetParameters();
MethodBuilder methodBuilder = typeBuilder.DefineMethod(
serviceMethod.Name,
serviceMethod.Attributes ^ MethodAttributes.Abstract,
serviceMethod.CallingConvention,
serviceMethod.ReturnType,
serviceMethod.ReturnParameter.GetRequiredCustomModifiers(),
serviceMethod.ReturnParameter.GetOptionalCustomModifiers(),
parameters.Select(p => p.ParameterType).ToArray(),
parameters.Select(p => p.GetRequiredCustomModifiers()).ToArray(),
parameters.Select(p => p.GetOptionalCustomModifiers()).ToArray());
ILGenerator ilGenerator = methodBuilder.GetILGenerator();
MethodInfo callAsyncMethod = getCallAsyncMethod(baseType, serviceMethod);
ilGenerator.Emit(OpCodes.Ldarg_0); // Push "this"
ilGenerator.Emit(OpCodes.Ldnull); // Push Func<> argument
ilGenerator.Emit(OpCodes.Call, callAsyncMethod); // Call CallAsync on the base client
ilGenerator.Emit(OpCodes.Ret);
}
}