2014-02-11 86 views
1

我使用.NET 4.0和動態在運行時需要調用系統.__ ComObject成員。我實例化以下列方式對象:調用GetMethod()在系統.__ ComObject總是返回null

dynamic DrApi; 
DrApi = Activator.CreateInstance(SprImportedTypes.DrApi); 

的類型聲明靜態類是這樣的:

internal static Type DrApi = Type.GetTypeFromProgID("DrApi.DrApi.1"); 

由於對象是動態的,我可以調用方法沒有任何困難:

string vers = string.Empty; 
DrApi.Version(ref vers); 

對於鞏固和本地化的錯誤處理,我想有一個可用於該對象上調用方法的單一程序。大多數方法需要REF /輸出參數,所以我目前正在返回值的對象數組會從反射回來:

public object[] Run(string method, params object[] args) 
{ 
    var p = new ParameterModifier(args.Length); 
    for (int i = 0; i < args.Length; i++) 
     p[i] = true; 
    ParameterModifier[] mods = { p }; 

    SprImportedTypes.DrApi.InvokeMember(method, BindingFlags.InvokeMethod, 
             null, DrApi, args, mods, null, null)); 

    return args; 
} 

雖然這工作,我沒有收到對我的方法的任何信息m調用,因此不能100%舒適地通過引用設置所有參數。

這裏就是我試過,不工作:

MethodInfo mInfo = SprImportedTypes.DrApi.GetMethod(methodName, BindingFlags.Instance | 
                BindingFlags.NonPublic | BindingFlags.Static); 

下面是從OLE類型庫瀏覽器的方法:

[id(0x00000009), helpstring("method Version")] 
HRESULT Version(
      [in, out] BSTR* VersionString, 
      [out, retval] long* pReturnValue); 

類實現其自身實現IDispatch接口,並且該方法是HRESULT,所以我不知道爲什麼它永遠不會返回任何東西。

回答

2

這可不行,COM確實支持的反思。所以你不能指望Type.GetMethod()返回任何東西。在COM中的後期綁定是單向的,你可以讓服務器按名稱執行一個方法,但它不會告訴你它支持什麼方法以及它們採用什麼參數。你應該從文檔中知道這一點。

你實際上有一個類型庫,所以在技術上你可以在運行時檢查它,看看它裏面是什麼。這遠遠超出了痛苦和完全不切實際。更簡單的是隻添加對類型庫的引用。你會得到自動生成的.NET包裝類型,你可以直接在你的代碼中使用。有關詳細信息,請查看有關Tlbimp.exe的MSDN文章。這將開啓許多好東西,如IntelliSense和編譯時錯誤檢查。代碼也運行得更快。不再需要動態。唯一的缺點是你會將你的代碼綁定到一個特定版本的COM服務器上,這個COM服務器是你的類型庫。但是當你的遲到呼叫與更新不兼容時,你當然仍然會崩潰,但沒有什麼神奇的解決方法。

+0

漢斯,感謝您的答覆。實際上,我開始將類型庫作爲參考,然後再進行動態更新,就像您說的那樣簡單得多,儘管與更新不兼容。我不會去訪問類型庫的所有版本,所以我認爲動態是正確的選擇。如果存在嚴重的性能劣勢,我可能必須退後一步並重新制定戰略。 –