我的.net代码有一个包含许多通用属性的对象。此对象返回到VBA代码。所有非泛型属性都运行良好,但我还需要访问通用值。有没有办法从VBA做到这一点?
[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 :(得分:4)
您不能直接执行此操作(如果VS正在进行COM注册,您应该看到如下警告:类型库导出器警告处理'NS.Obj.get_GetProp2(#1),Assy'。警告:类型库导出器在签名中遇到泛型类型实例。通用代码可能无法导出到COM。
你需要做的是制作一个非通用的包装器和一个暴露给COM的接口(假设你需要强类型的对象)。只要您在VBA中引用typelib并通过强类型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互操作世界太久不能记住它是什么。
答案 1 :(得分:0)
我发现this article描述了一个丑陋的黑客 - 通过反思调用一切。由于泛型值仍然作为对象返回,因此反射应该起作用,但是1)慢,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)
丑陋,但可行。