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 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版。