Dynamic与Typed会产生奇怪的结果

本文关键字:结果 Typed Dynamic | 更新日期: 2023-09-27 17:57:40

我想要使用SAP RPC OCX控件。在C#4中,以下代码运行良好:

System.Type t = System.Type.GetTypeFromProgID("SAP.Functions", true);            
dynamic fc = System.Activator.CreateInstance(t, false);
dynamic connection = fc.Connection;
connection.System = "";

以下代码不起作用(即使连接不是空的)

System.Type t = System.Type.GetTypeFromProgID("SAP.Functions", true);            
dynamic fc = System.Activator.CreateInstance(t, false);
var connection = fc.Connection as SAPLogonCtrl.Connection
connection.System = "";

引发以下错误:"试图读取或写入受保护的内存。这通常表明其他内存已损坏。"

然而,最奇怪的事实是:

System.Type t = System.Type.GetTypeFromProgID("SAP.Functions", true);            
dynamic fc = System.Activator.CreateInstance(t, false);
dynamic c1 = fc.Connection;
var c2 = fc.Connection as SAPLogonCtrl.Connection;
if (c1 == c2)
  c2.System = "";

执行最后一行并抛出相同的异常!!!将c2替换为c1按预期工作。。。

我觉得我错过了一些琐碎的事情,但我完全不知所措。。。请帮忙?

其他信息:更改自:

dynamic fc = System.Activator.CreateInstance(t, false);

至:

var fc = System.Activator.CreateInstance(t, false) as SAPFunctionsOCX.SAPFunctions;

没什么区别。c1仍然有效,而c2仍然无效。

附加信息#2:更改FC本身的属性也适用于这两种情况。

Dynamic与Typed会产生奇怪的结果

虽然看起来两次都在做同样的事情,但实际上完全不同:在第一个代码示例中:

dynamic connection = fc.Connection;
connection.System = "";

结果是获得fc.Connection,然后使用dynamic调用System =属性setter。动态语言运行库关闭并查询COM接口,并调用特定COM接口上的特定方法。实际上,你无法从C#方面看到它使用的是什么接口或方法。

在第二个例子中(我已经替换了var以使事情更加清楚):

SAPLogonCtrl.Connection connection = fc.Connection as SAPLogonCtrl.Connection
connection.System = "";

结果是得到fc.Connection,然后将其强制转换为SAPLogonCtrl.Connection。然后您尝试调用SAPLogonCtrl.Connection.System =,但它失败了。

我怀疑它失败了,因为该对象实际上不是SAPLogonCtrl.Connection的实例,但它可能是代理或其他对象。

大多数COM互操作被拆分为一个接口(很可能有一个SAPLogonCtrl.IConnection)和一个类。在调用方法时,通常需要通过接口调用dynamic代码将在幕后为您完成所有工作。

您可以尝试搜索接口,并使用该接口进行调用。如果最终SAPLogonCtrl.IConnection存在,则解决方案可能如下。

var connection = fc.Connection as SAPLogonCtrl.IConnection // note the I!
connection.System = "";

无论如何,在处理COM互操作时,请记住通过接口调用

您是否可以将实际控件添加为对项目的引用,并通过Visual Studio创建的互操作代码使用它,而不是尝试通过COM和反射创建它?

这只是一个想法,但由于dynamic在执行时才绑定,而var在编译时绑定,可能是fc类型不可用于连接吗?

编辑:作为一个次要问题,是否需要使用:

var连接=fc。连接为SAPLogonCtrl.Connection

你可以使用的地方:

SAPLogonCtrl.Connection Connection=fc。联系

我是不是错过了什么?为什么要将其设置为隐式类型,然后显式强制转换?

您必须在运行时意识到动态运行是一个Object,Object可以接受任何东西。这个简单的事实在C#4.0 开始时就已经指出了

注意:不同寻常的是,动态类型只存在于编译时;在运行时使用System.Object类型。这是一个小的实现细节,但值得记住,因为它可能会澄清下面的一些讨论。一旦你有了一个动态变量,你就可以访问它的成员(这里没有显示实际获取变量值的代码):myDynamicVar.DoSomething("With this!");

Watson,Karli;纳格尔,基督徒;佩德森、雅各布·哈默;里德,Jon D。;Skinner,Morgan(2011-02-08)。开始Visual C#2010(Wrox程序员对程序员)(第414页)。弗罗克斯。Kindle版。