如何通过COM Interop访问复杂对象的属性?

时间:2017-05-07 22:58:45

标签: c# c++ com com-interop

所以我有一个接口(IInterface1)暴露为ComVisible(true),ClassInterfaceType(ClassInterfaceType.None)。

我在该界面上有一个对象,ala:

public interface IInterface1
{
    Object1 object {get; set;}
}

对象一也是ComVisible(true),在一个单独的程序集中,ClassInterfaceType(ClassInterfaceType.None),看起来像这样:

public interface IObject1
{
   string MyProperty {get;set;}
}

在C#中,我还有以下课程:

public class Interface1 : IInterface1
{
    public IObject1 Object1 {get;set;}
}

从非托管C ++,我将如何访问Interface1.Object1.MyProperty?我导入TLH raw_interfaces_only,可以CreateInstance我的Interface1类,并访问Object1。如果我尝试在Object1上访问MyProperty,我会得到一个"指向不允许的不完整类类型"。

c ++代码如下:

Assembly1::Interface1Ptr interface1ptr;
HRESULT hrRetval = CoInitialize(NULL);
hrRetval = interface1ptr.CreateInstance(__uuidof(Assembly1::Interface1));
Assembly1::Object1 *object1;

hrRetval = interface1ptr.get_Object1(&object1);

这就是我被困的地方:

hrRetval = object1->get_MyProperty(varToStore); // This doesn't work.

欣赏任何指针(har har)。

1 个答案:

答案 0 :(得分:0)

您可以导入两个程序集,应该是:

Assembly1:

namespace ClassLibrary1
{
    [ComVisible(true)]
    public interface IObject1
    {
        string MyProperty { get; }
    }

    [ComVisible(true)]
    [ClassInterface(ClassInterfaceType.None)]
    public class Object1 : IObject1
    {
        public string MyProperty { get => "42"; }
    }
}

// AssemblyInfo.cs
[assembly: Guid("d1e7f7b4-3c3a-41e5-b0bf-5dec54050431")]

Assembly2:

namespace ClassLibrary2
{
    [ComVisible(true)]
    public interface IInterface1
    {
        IObject1 Object1 {get;}
    }

    [ComVisible(true)]
    [ClassInterface(ClassInterfaceType.None)]
    public class Interface1 : IInterface1
    {
        public IObject1 Object1 { get => new Object1(); }
    }
}

// AssemblyInfo.cs
[assembly: Guid("a7a14989-71da-49d4-87be-85c4b87bcaf0")]

C ++:

#include "stdafx.h"
#import "libid:d1e7f7b4-3c3a-41e5-b0bf-5dec54050431" raw_interfaces_only
#import "libid:a7a14989-71da-49d4-87be-85c4b87bcaf0" raw_interfaces_only

int main()
{
    CoInitialize(nullptr);

    ClassLibrary2::IInterface1Ptr i1;
    i1.CreateInstance(__uuidof(ClassLibrary2::Interface1));

    ClassLibrary1::IObject1Ptr o1;
    i1->get_Object1(&o1);

    BSTR bstr;
    o1->get_MyProperty(&bstr);

    CoUninitialize();
    return 0;
}
顺便说一句,你想要raw_interfaces_only的具体原因是什么?没有它会更容易和更安全:

ClassLibrary2::IInterface1Ptr i1;
i1.CreateInstance(__uuidof(ClassLibrary2::Interface1));

auto o1 = i1->Object1;
auto bstr = o1->MyProperty;