Type.InvokeMember with nullable parameter

本文关键字:parameter nullable with InvokeMember Type | 更新日期: 2023-09-27 18:31:55

项目

我开发了一个远程处理类,用于替换 WCF 的子集。这样做是因为我们的目标是使用 Unity3D 的移动平台,并且需要尽可能减少内存消耗。(所以我们不需要包括System.ServiceModel,它实际上的大小为2.7MB,这对于小型移动RAM来说已经很多了)

它现在适用于所有类型(

包括将使用我几年前编写的序列化程序序列化的复杂类型),并且它还能够处理复杂情况(A 调用 B,B 调用 A,A 返回某些内容,B 返回某些内容)。

方法调用

为了在目标站点上调用方法,我正在使用Type.InvokeMember它实际上适用于除可为空类型之外的大多数情况。这就是我面临的问题。在我的接口定义中,该方法如下所示:

public interface IServerContract 
{
    void SetUsageID(Int32? id);
}

ServerProxy(处理对远程方法调用的对象)我正在执行以下操作:

public class ServerProxy : ProxyBase
{
    public void SetUsageID(Int32? id)
    {
         RemoteCall("SetUsageID", id);
    }
}

像往常一样,参数id被装箱,因为RemoteCall的定义如下所示:

public void RemoteCall(String methodName, params Object[] arguments) { ... }

在这一点上,我只得到了一个System.Int32,而不是一个可为空的。我正在序列化参数并在目标计算机上反序列化它们。此时,我调用Type.InvokeMethod会导致异常,因为他找不到将Int32作为第一个参数的方法(不忽略此参数时为第二个)。

这个问题的最佳解决方案是什么?有薮猫的方式,但都会导致性能影响。

Type.InvokeMember with nullable parameter

int?的拳击规则确实意味着,一旦你把它作为object,你会看到:

  • null,没有更多的东西可以辨别
  • 空值仅称为不可为空的类型
    • 所以具体来说,通过(int)5(int?)5object内具有完全相同的外观

因此,可用的选项:

  • 确保方法名称是唯一的,因此您可以按名称唯一解析为MethodInfo,然后使用MethodInfo.Invoke(这可确保参数中没有歧义)
  • 尝试解析接受不可为空类型的方法,然后改为查找可为空的类型(对于多参数方法变得复杂)
  • 传递有关您正在调用的方法的更多元数据(增加大小)

不过,就我个人而言,我对这些事情的看法非常简单......与其尝试编码一个模糊的多参数方法,另一种选择是简化为始终传递单个基于 DTO 的参数 - 即,而不是SetUsageID(int?)你可以有SetUsage(SetUsageArgs)(或类似的东西),其中SetUsageArgs碰巧有一个属性。关键是:你现在只是编码一个DTO,一旦你反序列化了这个DTO,就没有歧义了。