Reflection.Emit 参数传递

发布于 2024-12-14 00:14:46 字数 1249 浏览 2 评论 0原文

我想为 WCF 服务创建一个自动生成的代理,这样我就可以避免手动创建服务代理。

使用反射发射,我创建了动态类生成的完整周期(从程序集到方法),并且我的方法生成的代码如下所示:

        bool isVoid;

        if ((isVoid = (methodInfo.ReturnType != typeof(void))))
            generator.DeclareLocal(methodInfo.ReturnType);

        generator.Emit(OpCodes.Ldarg_0);
        var channelProperty = baseType.GetMethod(ChannelPropertyGetName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetProperty);

        generator.EmitCall(OpCodes.Call, channelProperty, null);

        for (short index = 0; index < parameters.Count(); index++)
            generator.Emit(OpCodes.Ldarg, (index + 1));

        generator.Emit(OpCodes.Callvirt, methodInfo);

        if (isVoid)
        {
            generator.Emit(OpCodes.Stloc_0);
            generator.Emit(OpCodes.Ldloc_0);
        }

        generator.Emit(OpCodes.Ret);

我还有一个服务和适当的服务契约如下所示:

[ServiceContract]
public interface INamingService
{
    /// <summary>
    /// Resolve a name
    /// </summary>
    [OperationContract(Name = "GetName")]
    string GetName(string name);

}

但是当我尝试时要按指定名称(不为空)从此服务检索值,我发现客户端调用中出现的参数为空。因此,据我了解,我在 Emit 中犯了一个错误,并且参数没有传递。

有人可以告诉我如何解决这个问题吗?

I want to create an autogenerated proxy for WCF service that allows me to avoid manual creation of service proxies.

Using reflection emit, I've created the full cycle of dynamic class generation (from assembly to methods) and code of my method generation looks like so:

        bool isVoid;

        if ((isVoid = (methodInfo.ReturnType != typeof(void))))
            generator.DeclareLocal(methodInfo.ReturnType);

        generator.Emit(OpCodes.Ldarg_0);
        var channelProperty = baseType.GetMethod(ChannelPropertyGetName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetProperty);

        generator.EmitCall(OpCodes.Call, channelProperty, null);

        for (short index = 0; index < parameters.Count(); index++)
            generator.Emit(OpCodes.Ldarg, (index + 1));

        generator.Emit(OpCodes.Callvirt, methodInfo);

        if (isVoid)
        {
            generator.Emit(OpCodes.Stloc_0);
            generator.Emit(OpCodes.Ldloc_0);
        }

        generator.Emit(OpCodes.Ret);

I also have a service and appropriate service contract looks like so:

[ServiceContract]
public interface INamingService
{
    /// <summary>
    /// Resolve a name
    /// </summary>
    [OperationContract(Name = "GetName")]
    string GetName(string name);

}

but when I'm trying to retrieve value from this service by specified name (not null), I see that the parameter which comes up from client call is null. Thus, as far as I understand, I made a mistake in Emit and parameter doesn't passed.

Could anyone advise to me, how to resolve this issue?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

滥情稳全场 2024-12-21 00:14:46

这里有一些小要点:

  1. isVoid 似乎是一个糟糕的名字,因为它表明该方法返回 void。
  2. 您对本地的使用似乎没有必要 - 您只需存储到它,然后立即重新加载该值。
  3. 我不明白为什么您使用 EmitCall 作为属性获取器;您几乎肯定应该使用 Emit (请参阅 文档)。

然而,我不明白为什么你认为问题出在你的IL一代;对我来说,听起来更有可能是您

  1. 错误地声明了动态方法,或者
  2. 以某种方式错误地连接了代理。

Here are a few minor points:

  1. isVoid seems like a poor name since it indicates that the method does not return void.
  2. Your use of a local seems unnecessary - you are simply storing to it and then immediately reloading that value.
  3. I don't understand why you're using EmitCall for the property getter; you should almost certainly be using Emit instead (see the documentation).

However, I don't see why you think that the problem is with your IL generation; to me it sounds more likely that you are either

  1. Declaring your dynamic method incorrectly, or
  2. Mis-wiring the proxy somehow.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文