2011-05-26 44 views
7

我有我想要使用的SAP RPC OCX控件。 在C#4下面的代碼工作正常:Dynamic vs Typed會產生奇怪的結果

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

下面的代碼無法正常工作(即使連接是NOT NULL)

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

請告訴我們什麼回報如下:'c1.GetType()的ToString()'和'c2.GetType(。 )的ToString()'。 – 2011-05-26 14:37:01

+0

兩者都返回System .__ ComObject – 2011-05-26 14:44:55

+0

我在黑暗中拍攝了一個鏡頭,但是'fc.Connection'實際上是一個從'SAPLogonCtrl.Connection'繼承的類的實例。這就是爲什麼你的'as'沒有返回null,爲什麼你看到不同的行爲。這可能是丹尼爾試圖通過問你的類型而得到的。 – Greg 2011-06-02 19:02:53

回答

1

雖然它看起來像你做同樣的事情兩次,它實際上是完全不同的:在第一個代碼示例:

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

發生的事情是你fc.Connection,然後調用System =屬性setter使用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互操作時務請致電

0

您可以不只是將實際的控件添加爲項目的引用,而是通過Visual Studio創建的interop代碼使用它,而不是試圖通過COM和反射來創建它?

+0

這正是我所做的 - 提到的類都是由Visual Studio生成的。如果您的意思是「將控件拖到窗體中」 - 我不能這樣做,因爲它不是Windows窗體應用程序,儘管我懷疑結果與Visual Studio將生成的代碼相同。 – 2011-06-06 13:40:31

0

只是一個想法,但由於動態是不會執行時間綁定,而var是在編譯時綁定,可能是fc的類型不可用於連接?

編輯:作爲一個方面的問題,有沒有必要使用:

VAR連接= fc.Connection作爲SAPLogonCtrl.Connection

在那裏你可以只使用:

SAPLogonCtrl.Connection連接= fc.Connection;

我錯過了什麼嗎?你爲什麼要將它設置爲一個隱式類型,然後明確地轉換它?

0

你必須在運行時實現動態運行作爲對象和對象可以接受任何東西。這個簡單的事實在C#開始指出4.0

注意不同尋常的是,動態類型只存在於編譯時;在運行時,將使用System.Object類型。這是一個較小的實現細節,但值得記住,因爲它可能會澄清下面的一些討論。一旦你有一個動態變量,你可以繼續訪問它的成員(實際獲得變量值的代碼在這裏沒有顯示):myDynamicVar.DoSomething(「With this!「);

Watson,Karli;內格爾,基督徒;彼得森,雅各布·哈默;裏德,喬恩D。 Skinner,Morgan(2011-02-08)。從Visual C#2010開始(Wrox程序員到程序員)(p。414)。 Wrox的。 Kindle版。

+0

這對您有幫助嗎? – 2011-10-11 11:13:01

相關問題