2015-11-06 42 views
0

我有用C#編寫的.dll,我在Visual Basic中使用它來創建Com對象。我從我的Visual Basic代碼中調用C#函數。我對這項技術很陌生,遇到這樣的問題。在C#代碼中,我有一個方法,它接收一個回調函數作爲參數,從服務器獲取數據然後調用該回調函數。現在我需要從我的Visual Basic代碼中調用該函數並傳遞迴調函數。 我認爲它應該是這個樣子將回調函數從Visual Basic傳遞到C#

// C# dll 
public bool GetDataFromServer(int someData1, Action<MyCustomType> callback, int someData2) 
{ 
    // request to server, get data, create an object of MyCustomType 
    // call callback and pass MyCustomType object to it as a parameter 
} 

// Visual Basic part 
Public Sub DisplayData(ByRef resp As My_Dll.MyCustomType) 
    ' do something with resp 
End Sub 

// call Dll method 
My_Dll.GetDataFromServer(1, DisplayData, 2) ' I get a compile error 

但我無法得到它的工作,但事件不會編譯。我收到一個編譯錯誤,說「參數不可選」。我也試着通過回調函數AddressOf,但我再次收到錯誤 - 「AddressOf運算符的使用無效」。 現在我的問題是 - 我做錯了什麼?將回調函數從Visual Basic傳遞給C#並將其調用的正確方法是什麼?

謝謝你的時間!

+0

如何使用'async'和'await'來代替回調? –

+0

其實我需要回撥,因爲我要訂閱。所以我的回調應該一次又一次地根據服務器響應來調用。 – nabroyan

+0

VBA沒有代表。您是否考慮傳遞一個C#可以存儲並在完成時調用的對象? – DanL

回答

0

任何包含泛型的東西都不是COM可見的,所以您的GetDataFromServerAction<MyCustomType>不是COM可見的。您必須在非泛型類上定義一個方法,而不使用泛型類型參數,也不使用泛型參數或返回類型。

在COM中傳遞迴調的通常方式是將接口指針與要調用的方法一起傳遞。避免採用AddressOf的方法,但是可行的,一旦你想讓回調工作在進程外,這是非常糟糕的做法。

IDispatch對象的一個​​常見技巧是使用默認方法DispId 0(DISPID_VALUE)定義一個類,該類可以由COM服務器通過IDispatch::Invoke調用。在某些語言中,比如JScript,可以通過這種技術調用對象。

要了解如何在VB6/VBA中執行此操作,請搜索VB_UserMemId。從本質上講,你必須編輯在其原始格式的類文件(在VBA,則必須將其導出),並添加屬性,如:

Sub Call() 
Attribute Call.VB_UserMemId = 0 
End Sub 

在VBA中,你會從編輯刪除類和進口文件。結果是Call方法現在有DispId 0.您可以隨意調用它,但請記住要編輯Sub名稱和Attribute

在C#中,我認爲實現這種調用的唯一途徑與dynamic變量有:

obj[0] 

或通過Type.InvokeMember或類似IDispatch::Invoke方法:

obj.GetType().InvokeMember("", BindingFlags.InvokeMethod, null, obj, null); 

後者更可靠並且你傳遞你想要的參數,而前者使用誤導性的語法並強制你傳遞一個參數。

一般來說,如果你控制整個情況,並且你不需要可調用的對象,只需要一個普通的方法。

關於AddressOf錯誤,此操作符處理模塊過程和函數,因此您看到的錯誤可能是因爲DisplayOptionQuotes是一種方法。