首页 > 解决方案 > 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_1Ldarg_2

非常感谢任何和所有帮助。

标签: c#wrapperreflection.emitemitilgenerator

解决方案


推荐阅读