1

我想在 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-> sQueryString

给出错误。

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

谁能建议我错在哪里。

谢谢,加根

4

2 回答 2

2

一切都按照应有的方式运行 :)

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

您的实现,即AQSEntity类,应该实现所有IEntity成员。现在在该类中声明的方法是该类的成员,它们没有IEntity任何关系。

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

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

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

编辑:

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

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

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

2) 更少的工作,但更脆弱:标记AQSEntityClassInterfaceType.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标记接口的唯一缺点是,如果您想将接口用作泛型的约束

于 2013-04-29T09:32:46.467 回答
0

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

于 2013-04-29T08:45:39.910 回答