2013-09-26 73 views
2

我有一個類:是否可以通過COM互操作轉發委託?

public class A 
{ 
public delegate void SetTextDel(string value); 
public void Test() 
{ 
     SetTextDel setText = someInterface.SetText; 
     icom.Set(setText); 
} 
} 

[ComVisible(true), Guid("81C99F84-AA95-41A5-868E-62FAC8FAC263"), InterfaceType(ComInterfaceType.InterfaceIsDual)] 
    public interface Icom 
    { 
     void Set(Delegate del); 
    } 

[ComVisible(true)] 
    [Guid("6DF6B926-8EB1-4333-827F-DD814B868097")] 
    [ClassInterface(ClassInterfaceType.None)] 
    [ComDefaultInterface(typeof(Icom))] 
    public class B : Icom 
    { 
     Set(Delegate del) 
     { 
       del.DynamicInvoke("some text"); 
     } 
    } 

而且我得到了設置(代表DEL)targetinvocation例外。有沒有更好的方式來轉發委託作爲參數?或者我在這裏犯了一些我沒有看到的錯誤。我想要做的是傳遞someInterface.SetText這個方法作爲參數。感謝您的幫助。

+0

此代碼是否可用? – JeremiahDotNet

+0

是的,COM正在被識別,這只是簡短的版本。我只需要將代理作爲參數傳遞給B類的幫助。 –

回答

6

以下工作:

public class A 
{ 
    public delegate void SetTextDel(string value); 

    void TestSetText(string value) 
    { 
     MessageBox.Show(value); 
    } 

    public void Test(Icom icom) 
    { 
     SetTextDel del = TestSetText; 
     icom.Set(del); 
    } 
} 

[ComVisible(true), Guid("81C99F84-AA95-41A5-868E-62FAC8FAC263"), InterfaceType(ComInterfaceType.InterfaceIsDual)] 
public interface Icom 
{ 
    void Set(Delegate del); 
} 

[ComVisible(true)] 
[Guid("6DF6B926-8EB1-4333-827F-DD814B868097")] 
[ClassInterface(ClassInterfaceType.None)] 
[ComDefaultInterface(typeof(Icom))] 
public class B : Icom 
{ 
    public void Set(Delegate del) 
    { 
     del.DynamicInvoke("some text"); 
    } 
} 

private void buttonTest_Click(object sender, EventArgs e) 
{ 
    var a = new A(); 
    var b = new B(); 

    a.Test(b); 
} 

接下來,如果你正在尋找通過從C++Icom.Set一個回調函數,以下將工作太:

[UnmanagedFunctionPointer(CallingConvention.StdCall)] 
public delegate void SetTextDel([MarshalAs(UnmanagedType.BStr)] string value); 

[ComVisible(true), Guid("81C99F84-AA95-41A5-868E-62FAC8FAC263"), InterfaceType(ComInterfaceType.InterfaceIsDual)] 
public interface Icom 
{ 
    void Set([MarshalAs(UnmanagedType.FunctionPtr)] SetTextDel del); 
} 

[ComVisible(true)] 
[Guid("6DF6B926-8EB1-4333-827F-DD814B868097")] 
[ClassInterface(ClassInterfaceType.None)] 
[ComDefaultInterface(typeof(Icom))] 
public class B : Icom 
{ 
    public void Set(SetTextDel del) 
    { 
     del("some text"); 
    } 
} 

確保將您的C#和C++項目都編譯爲32位代碼。 C++的回調函數應聲明爲這樣:

static HRESULT __stdcall SetTextDelCallback(BSTR value) 
{ 
    return S_OK; 
} 

最後,合適的方式來實現此,IMO,是簡單地定義一個回調接口(如下面ISetCallback)和傳遞對象實現這樣的接口,而不是代表。 ISetCallback可以用任何語言實現,無論是C#還是C++:

[ComVisible(true), Guid("2FE5D78D-D9F2-4236-9626-226356BA25E7")] 
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
public interface ISetCallback 
{ 
    void OnSetText(string value); 
} 

public class A : ISetCallback 
{ 
    public void OnSetText(string value) // ISetCallback 
    { 
     MessageBox.Show(value); 
    } 

    public void Test(Icom icom) 
    { 
     icom.Set(this); 
    } 
} 

[ComVisible(true), Guid("81C99F84-AA95-41A5-868E-62FAC8FAC263"), InterfaceType(ComInterfaceType.InterfaceIsDual)] 
public interface Icom 
{ 
    void Set(ISetCallback callback); 
} 

[ComVisible(true)] 
[Guid("6DF6B926-8EB1-4333-827F-DD814B868097")] 
[ClassInterface(ClassInterfaceType.None)] 
[ComDefaultInterface(typeof(Icom))] 
public class B : Icom 
{ 
    public void Set(ISetCallback callback) 
    { 
     callback.OnSetText("some text"); 
    } 
} 

private void buttonTest_Click(object sender, EventArgs e) 
{ 
    var a = new A(); 
    var b = new B(); 

    a.Test(b); 
} 
+1

Man @Noseration你是一個天才。非常感謝你。 –

+0

沒問題,很高興幫助。 – Noseratio