从VBA访问.NET通用对象

时间:2009-09-24 20:56:17

标签: c# .net vba com interop

我的.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

2 个答案:

答案 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)

丑陋,但可行。