2009-09-24 97 views
3

我的.net代碼具有包含許多通用屬性的對象。該對象返回到VBA代碼。所有的非泛型屬性都運行良好,但我也需要訪問泛型值。有沒有辦法從VBA做到這一點?從VBA訪問.NET通用對象

[ClassInterface(ClassInterfaceType.AutoDual)] 
public class Obj 
{ 
    public string GetProp1() {...} 
    public IList<MyCustomType> GetProp2() {...} 
} 

VB代碼:

Sub Test() 
    Dim o As Program.Obj 
    Set o = New Program.Obj 
    Set p2 = hp.GetProp2() 

    set p2_0 = p2(0) ' doesn't work 

End Sub 

回答

0

我發現this article描述了一個醜陋的黑客 - 通過反思調用一切。由於通用值仍作爲對象返回,因此反射應該起作用,但會很慢,2)容易出錯,以及3)調用非常不方便。

正如文章顯示,我會使用工具的方法具有以下特徵:

public object GetProperty(object Instance, string Property) 
public object InvokeMethod(object Instance, string Method) 
public object InvokeMethod_OneParm(object Instance, string Method, object Parm1) 
public object InvokeMethod_TwoParms(object Instance, string Method, object Parm1, object Parm2) 
public void SetProperty(object Instance, string Property, object Value) 

醜陋,但可行的。

+0

警告建議修復此問題,例如@Matt Davis的回答 – Dude0001 2016-10-22 12:44:08

4

你不能做到這一點直接(如果VS做你的COM註冊,你會看到類似的警告:類型庫導出警告處理「NS.Obj。 get_GetProp2(#1),Assy'警告:類型庫導出程序在簽名中遇到一個通用類型實例,通用代碼可能不會導出到COM。

您需要做的是使一個非通用包裝器和一個暴露給COM的接口(假設你需要強類型的對象),只要你引用類型庫在VBA,並通過強類型的VBA裁判訪問你的對象,你可以這樣做:

[ComVisible(true)] 
[ClassInterface(ClassInterfaceType.AutoDual)] 
public class Class1 
{ 
    public IMyListOfString Strings {get; set;} 
    public Class1() 
    { 
     Strings = new MyListOfString() { "Foo", "Bar", "Baz" }; 
    } 
} 

[ComDefaultInterface(typeof(IMyListOfString))] 
public class MyListOfString : List<string>, IMyListOfString { } 

[ComVisible(true)] 
[InterfaceType(ComInterfaceType.InterfaceIsDual)] 
public interface IMyListOfString 
{ 
    [DispId(0)] 
    string this[int idx] { get; set; } 
} 

有一個竅門能讓而不引用在VBA的管理類型庫的工作(例如,後期綁定),但是,我已經遠離COM互操作世界太久,無法記住它是什麼。