2013-07-16 122 views
2

我將代碼從VSTO移動到ExcelDna,並遇到奇怪的錯誤。將默認數組參數設置爲空的C#COM函數

我在Visual Studio中創建了一個新的項目,它將包含我以前的VSTO函數。爲了生成.tlb文件,我將在Excel VBA參考以訪問VBA中的這些功能,我查了選項「註冊爲COM互操作」

對於一個功能我有錯誤:

「程序集」C:\ MyProj.dll「無法轉換爲類型庫。類型庫導出程序在處理'GetArrayObject'時遇到錯誤。錯誤:類型不匹配。」

在COM可見接口的功能GetArrayObject的定義是:

[ComVisible(true)] 
//[InterfaceType(ComInterfaceType.InterfaceIsDual)] 
public interface IAddInUtilities 
{ 
    object[,] GetArrayObject(string[] rows = null); 
} 

下定義的工作原理:

object[,] GetArrayObject(string[] rows); 

它是在COM一個已知的限制?它可能是由於C++的限制(Default values for array arguments)?是否有一個原因適用於VSTO而不是COM?

非常感謝您的幫助

回答

3

這不是一個很好的錯誤消息。當您在界面的工作版本上運行Oleview.exe文件+查看Typelib時,可以看到問題。你會看到:

interface IAddInUtilities : IDispatch { 
    [id(0x60020000)] 
    HRESULT GetArrayObject(
        [in] SAFEARRAY(BSTR) rows, 
        [out, retval] SAFEARRAY(VARIANT)* pRetVal); 
}; 

說明如何使用String []被編組爲一個SAFEARRAY,標準的自動化類型的數組。並注意它是如何通過價值傳遞的,而不是通過引用。這意味着它不能爲空。否則不支持爲SAFEARRAY指定默認值。

您必須通過引用傳遞數組,ref關鍵字在C#中。但是,隨後會遇到C#語言規則的問題,您無法再指定默認值。

接下來的嘗試是強制將數組作爲指針BSTR *進行封送。這就是SAFEARRAY的對映體,因爲你現在不得不添加一個額外的參數來陳述數組中的元素數量,因爲COM服務器不能從普通指針中找出它。像這樣:

public interface IAddInUtilities { 
    object[,] GetArrayObject(
     int rowcnt, 
     [MarshalAs(UnmanagedType.LPArray)]string[] rows = null 
    ); 

它轉換得很好。但是,如果您現在使用Oleview.exe查看類型庫,則會看到:

interface IAddInUtilities : IDispatch { 
    [id(0x60020000)] 
    HRESULT GetArrayObject(
        [in] long rowcnt, 
        [in, optional, defaultvalue("")] BSTR* rows, 
        [out, retval] SAFEARRAY(VARIANT)* pRetVal); 
}; 

呃,錯誤的默認值。唯一的其他選擇是使用從Oleview.exe獲得的IDL,編輯它以更改defaultvalue(),使用midl.exe編譯它以生成類型庫並使用Tlbimp.exe生成一個互操作庫。然後您可以使用Project + Add Reference將其添加到項目中。不完全如此確定,這仍然值得輕微便利的麻煩,這是由你來打電話。