c# - ILGenerator:如何生成一个 Func<> 作为参数传递
问题描述
我正在尝试围绕由接口定义的服务创建代理包装器,以向服务的开发人员用户“隐藏”客户端特定的调用代码。
我已经能够生成大部分包装类本身,但现在正在努力为预先存在的客户端调用生成 Func 参数。
一个示例 TService 有一个接口:
public interface ITestService
{
public Task ServiceMethodAsync();
public Task<TestDTO> ServiceMethodWithResultAsync();
}
客户端实现的签名是:
public Task<TResult> CallAsync<TResult>(Func<TService, Task<TResult>> operation);
public Task CallAsync(Func<TService, Task> operation);
直接调用时,开发人员当前会写如下内容:
var result = await client.CallAsync(service => service.ServiceMethodWithResultAsync(requestDTO));
虽然首选的选项是他们可以调用:
var result = await service.ServiceMethodWithResultAsync(requestDTO);
因为这允许 DI 使用 IService 接口注入本地服务或我的远程包装器,并且开发人员不需要考虑它是远程服务还是本地服务。
我目前让我的 typebuilder 生成所需的代码来创建从客户端继承的包装类baseType
并针对它定义所有接口方法,但目前将 null 作为Func<TService, Task<TResult>> operation
.
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);
}
}
从这里我有点坚持到底如何定义 Func<>service => service.ServiceMethodWithResultAsync(requestDTO)
包括requestDTO
我期望/假设的参数Ldarg_1
等Ldarg_2
?
非常感谢任何和所有帮助。
解决方案
推荐阅读
- python - 用链式掩码替换 numpy 数组元素
- xml - Perl XPath:使用“and”返回两个节点
- python - PDF到Python中的文本在图像文件中返回空结果
- reactjs - 设置输入初始值并使用钩子更新 onChange。错误:渲染的钩子比上一次渲染时更多
- java - IntelliJ IDEA 或 Eclipse 中是否有像 MATLAB 中的工作区一样工作的函数窗口?
- r - 如何使用带有 R 星包的多边形从栅格中提取值?
- regex - 试图理解正则表达式片段 (/[-/\\^$*+?.()|[\]{}]/g, '\\$&')
- c# - 使用 Microsoft Graph 邀请消费者用户加入 B2C 租户
- linux - 仅在 Linux 上为 ASP.NET Core 3.1 csproj 添加 PackageReference:操作系统的 csproj 条件变量列表?
- ansible - 一种列出 playbook 使用的 Ansible 模块的方法