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
作为第一个参数的方法(不忽略此参数时为第二个)。
这个问题的最佳解决方案是什么?有薮猫的方式,但都会导致性能影响。
int?
的拳击规则确实意味着,一旦你把它作为object
,你会看到:
-
空值
null
,没有更多的东西可以辨别 -
非空值仅称为不可为空的类型
- 所以具体来说,通过
(int)5
和(int?)5
在object
内具有完全相同的外观
- 所以具体来说,通过
因此,可用的选项:
- 确保方法名称是唯一的,因此您可以按名称唯一解析为
MethodInfo
,然后使用MethodInfo.Invoke
(这可确保参数中没有歧义) - 尝试解析接受不可为空类型的方法,然后改为查找可为空的类型(对于多参数方法变得复杂)
- 传递有关您正在调用的方法的更多元数据(增加大小)
不过,就我个人而言,我对这些事情的看法非常简单......与其尝试编码一个模糊的多参数方法,另一种选择是简化为始终传递单个基于 DTO 的参数 - 即,而不是SetUsageID(int?)
你可以有SetUsage(SetUsageArgs)
(或类似的东西),其中SetUsageArgs
碰巧有一个属性。关键是:你现在只是编码一个DTO,一旦你反序列化了这个DTO,就没有歧义了。