使用COM在C ++中实例化C#类成员

时间:2013-04-29 08:37:52

标签: c# c++ class com

我想在C ++中创建一个C#类对象并设置其成员字段。 虽然我能够创建一个C ++类对象,但我无法访问它的成员并设置成员字段值。

/// <summary>
/// Class for AQS Entity
/// </summary>
[ClassInterface(ClassInterfaceType.None)]
[Guid("70F12A44-B91D-474D-BD70-32B1ACE041D6")]
[ProgId("AQSEntity")]
public class AQSEntity : IEntity
{

    public AQSEntity()
    {
        sRecoveryDBName = String.Empty;
        arrSourceMailboxesEntity = null;
        sQueryString = String.Empty;
    }

    [MarshalAs(UnmanagedType.BStr)]
    public string sRecoveryDBName = string.Empty;

    [MarshalAs(UnmanagedType.ByValArray)]
    public MailBoxCollection arrSourceMailboxesEntity;

    [MarshalAs(UnmanagedType.BStr)]
    public string sQueryString;


}

并且IEntity类定义如下

[Guid("5C71057E-9FD9-47D5-B022-8D5F9C7007D3")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IEntity
{
}

在C ++中,

IEntity* pTest1 = NULL;
hr = CoCreateInstance(__uuidof(**AQSEntity**),NULL,CLSCTX_INPROC_SERVER,__uuidof(IEntity),(void**)&pTest1);

我想在C ++中访问AQSEntity类的成员。但是我无法访问它们。

pTest1-&GT; sQueryString

给出错误。

  

'sQueryString':不是。的成员   'AsigraExchange :: IEntity'C:\ PROJECTS \ COM \ COMClient \ COMClient.cpp 168

任何人都可以建议我错在哪里。

谢谢, GAGAN

2 个答案:

答案 0 :(得分:2)

一切都表现得如此:)

在您的C ++项目中,您可以访问IEntity接口上声明的所有方法,这些方法都没有。

您的实施,即AQSEntity课程,应实施所有IEntity成员。现在在该类中声明的方法是类的成员,它们与IEntity无关。

这意味着您需要在IEntity接口中声明所有必需的方法,然后在AQSEntity中实现它们。请注意,您还要公开类的字段,而不是方法。您将必须定义方法(或属性,它们将转换为C ++方面的方法),然后实现它们。类似的东西:

public interface IEntity
{
    public string RecoveryDBName { get; }
}

您还必须在界面中指定[MarshalAs]属性,尽管UnmanagedType.BStr是字符串的默认属性,因此您可以省略它们。

编辑:

根据评论,似乎IEntity只是一个标记界面,不打算作为API公开(属性可能是更好的选项,因为IEntity不会在客户端上使用无论如何)。

在这种情况下,有两种选择:

1)更好的方法,虽然它需要更多的工作:从IAQSEntity派生IEntity接口,在其上声明方法,并在AQSEntity类上实现

2)工作量减少,但更脆弱:将AQSEntity标记为ClassInterfaceType.AutoDual而不是ClassInterfaceType.None - 这会将成员公开给COM客户端,但版本会更难以及还将公开基类型成员。

以下是我要选择的内容:

[ClassInterface(ClassInterfaceType.None)]
...
[Entity]  // instead of IEntity marker interface
public class AQSEntity : IAQSEntity
{
    public string RecoveryDbName { get; }
}

[Guid("...")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IAQSEntity // no base interface IEntity!
{
    string RecoveryDbName { get; }        
}

使用Entity属性而不是IEntity标记接口的唯一缺点是,如果要将接口用作泛型的约束

答案 1 :(得分:0)

您的界面确实不包含任何成员。您需要将成员放入界面,然后在您的类中实现该界面。