我有想要使用的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 = "";
执行最后一行并抛出相同的异常!!! 用c1替换c2按预期工作...
我觉得我错过了一些微不足道的事情,但我完全失去了...... 请帮帮忙?
其他信息: 改变自:
dynamic fc = System.Activator.CreateInstance(t, false);
为:
var fc = System.Activator.CreateInstance(t, false) as SAPFunctionsOCX.SAPFunctions;
没有任何区别。 c1仍然有效,而c2仍然没有。
其他信息#2: 更改FC本身的属性也适用于这两种情况。
答案 0 :(得分:1)
虽然看起来你两次都在做同样的事情,但它实际上完全不同:在第一个代码示例中:
dynamic connection = fc.Connection;
connection.System = "";
您获得fc.Connection
后会发生什么,然后使用System =
调用dynamic
属性设置器。动态语言运行库关闭并查询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互操作时通过界面调用
答案 1 :(得分:0)
您是否可以将实际控件添加为项目的引用并通过Visual Studio创建的互操作代码使用它,而不是尝试通过COM和反射创建它?
答案 2 :(得分:0)
只是一个想法,但由于动态直到执行时才被绑定,而var在编译时被绑定,可能是fc的类型不可用于连接吗?
编辑:作为一个副作用,是否有任何需要使用:
var connection = fc.Connection as SAPLogonCtrl.Connection
您可以使用的地方:
SAPLogonCtrl.Connection connection = fc.Connection;
我错过了什么吗?为什么要将它设置为隐式类型然后显式地转换它?
答案 3 :(得分:0)
你必须在运行时实现动态运行作为对象和对象可以接受任何东西。这个简单的事实在Beginning C#4.0
中指出注意不同寻常,动态类型仅在编译时存在;在运行时,使用System.Object类型。这是一个次要的实现细节,但值得记住,因为它可能会澄清下面的一些讨论。一旦你有了一个动态变量,就可以继续访问它的成员了(这里没有显示实际获取变量值的代码):myDynamicVar.DoSomething(“With this!”);
Watson,Karli; Nagel,Christian;佩德森,雅各布汉默; Reid,Jon D。;斯金纳,摩根(2011-02-08)。从Visual C#2010开始(Wrox程序员到程序员)(p.414)。 Wrox的。 Kindle版。