2015-11-20 61 views
1

我有一個第一C#組件暴露一個類和枚舉RuntimeBinderException經由動態

namespace TestComLibraryInCSharp 
{ 
    [Guid("A5AE3B4C-7788-4394-A949-98A9F78A8E00")] 
    [ComVisible(true)] 
    public enum ColorType 
    { 
     Red = 0, 
     Green = 1, 
     Blue = 2 
    } 

    [Guid("EF5D9F9C-DAAB-472E-A418-114F0352F06E")] 
    [InterfaceType(ComInterfaceType.InterfaceIsDual)] 
    [ComVisible(true)] 
    public interface IComClassUsingEnum 
    { 
     void Select(ColorType color); 
    } 

    [Guid("5EDE0D14-3A3B-41E7-93BC-40868BC68655")] 
    [ClassInterface(ClassInterfaceType.None)] 
    [ComVisible(true)] 
    public class ComClassUsingEnum : IComClassUsingEnum 
    { 
     public void Select(ColorType color) 
     { 
      MessageBox.Show("you have selected " + color.ToString()); 
     } 
    } 

} 

在另一組件傳遞枚舉值其他然後0到一個.net的COM大會我想用動態

來測試上述接口
public void DoTestColor() 
    { 
     Type type = Type.GetTypeFromProgID("TestComLibraryInCSharp.ComClassUsingEnum"); 
     dynamic c = Activator.CreateInstance(type); 

     c.Select(0); // this works 
     c.Select(1); // this throws RuntimeBinderException 
    } 

c.Select(0)的作品表示在MessageBox

c.Select(1)(或0除外任何其它數目)將產生此異常

An unhandled exception of type 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException' occurred in System.Core.dll 
Additional information: The best overloaded method match for 'TestComLibraryInCSharp.ComClassUsingEnum.Select(TestComLibraryInCSharp.ColorType)' has some invalid arguments 
在VBA

,後期綁定,一切正常

Dim c As Object 
Set c = CreateObject("TestComLibraryInCSharp.ComClassUsingEnum") 
c.Select 1 

什麼是通過枚舉值在C#中後期綁定正確的方法是什麼?

回答

1

這是一個非常好的例子,它演示了在.NET中編寫COM服務器測試代碼實際上並不真正測試COM互操作。爲什麼IDE反對添加對類型庫的引用是一個非常合理的抱怨。 CLR不容易被愚弄,它可以在運行時看到你創建了一個.NET對象,它不會爲它創建一個RCW。不要讓你的生活變得困難,只是因爲它更高效。

這個例外是完全正常的。 DLR遵循C#語言規則,只有默認值(0)可以隱式轉換爲枚舉類型。它堅持要看到ColorType,否則你會在C#程序中使用強制轉換。在後期的情況下,這非常難以實現,您不能將枚舉類型設置爲ProgId。需要某種偷偷摸摸的後門反射代碼,遠遠超出了理智的測試。

鑑於你沒有實際上測試COM互操作,你可能會拋出問題並添加一個正常的.NET引用。現在很簡單。只有VBA測試代碼執行COM互操作管道。

+0

我擔心這是答案 - 來自你我擔心它是正確的。我堅決反對這樣的事實,即不允許這是合法或合理的,但這不是重點。 – ekt

+0

關於此CLR優化,我收到了很多廢話。就好像我對這個設計選擇負責一樣。我回答這個問題的唯一原因是因爲它是一個非常出色的例子,可以清楚地展示底層實現細節。做得好。 –

+0

與我以前的評論我根本不想批評你的答案。我只想指出,我認爲這個.net設計的決定是有問題的。不想暗示你的責任。感謝您的完整答案。 – ekt

0

多達漢斯是正確的,一個解決方案可能是這個

public ColorType GetColorTypeFromInt(int colorTypeAsInt) 
{ 
    return (ColorType) colorTypeAsInt; 
} 

是,COM庫,暴露出從一個int強制轉換成適當的枚舉類型(這也許就是一些輔助方法漢斯被稱爲'偷偷摸摸的後門')。

很醜,但回答我的原始問題。