希望问题很清楚,但为了清楚起见,请将其填妥:
我有一个VB6 dll,它定义了我在C#dll中引用的枚举。 C#dll以正确的方式定义CCW,其中idispatch接口声明了一个函数,其返回类型是枚举。
当运行regasm时,我收到一个警告,表明枚举不是COM可见,因此不会导出该函数。因为它是在我的VB6库中定义的,所以我认为它已经是COM可见的,因为它是在COM dll中定义的。
我意识到我可以停止搞乱并使用int来传递枚举并且只是在任何一端进行投射,但这是令人沮丧的,我想知道是否存在一种方式。
根据要求,这里有一些示例代码:
VB6 dll定义了一个枚举
Public Enum myEnum
first = 0
second = 1
End Enum
这会通过互操作导入到C#中,如果您查看元数据,它看起来像这样
[Guid("EnumGUID")]
public enum myEnum
{
first = 0,
second = 1
}
然后定义CCW接口
[ComVisible(true)]
[Guid("InterfaceGuid")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IMyCCWInterface
{
[DispId(1)]
myEnum myFunction();
}
Regasm抱怨myEnum不可见。我必须同意它,因为元数据视图没有com visible属性。奇怪的是,如果我在VB dll中使用其他类型定义函数的参数我没有抱怨,它似乎是枚举,我猜它是因为我实际上暴露了VB6枚举的交错实现而不是实际的枚举。
所以我想我理解这个问题,我想知道的是,如果有一种方法可以使用不涉及黑客攻击任何中间或自动生成的代码的枚举。
答案 0 :(得分:2)
看起来解决方案是在C#项目中为导入的COM程序集设置“Embed Interop Types”属性为False。
为了测试这个,我创建了一个VB COM dll为StackOverflow.ExampleCom
,其中包含以下代码
Public Enum EThing
eThingOne = 1
eThingTwo = 2
End Enum
Private mThing As EThing
Private Sub Class_Initialize()
mThing = eThingOne
End Sub
Public Property Let Thing(newVal As EThing)
mThing = newVal
End Property
Public Property Get Thing() As EThing
Thing = mThing
End Property
然后我创建了一个C#类项目并导入了这个StackOverflow COM库。然后,C#中的以下代码创建一个COM对象,该对象重新公开VB代码中定义的枚举类型,从而创建OP描述的相同情况。
using System;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using StackOverflow;
namespace EnumDemo
{
[ComVisible(true)]
[Guid("c30d35fe-2c7f-448b-98be-bd9be567ce70")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IEnumDemo
{
[DispId(1)]
EThing Thing
{
get;set;
}
}
[ComVisible(true)]
[Guid("af328c82-08e3-403e-a248-8c46e27b48f3")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("StackOverflow.EnumDemo")]
public class EnumDemo
{
private EThing mThing = EThing.eThingOne;
public EThing Thing { get { return mThing; } set { mThing = value; } }
}
}
如果我们构建它然后尝试使用regasm /tlb:EnumDemo.tlb bin\Debug\EnumDemo.dll
从此程序集创建一个类型库,那么我会收到有关使用非COM可见值类型的警告。但是,一旦对VB COM dll的引用将“嵌入互操作类型”设置为false,警告就会消失,并且使用OleView检查生成的类型库是否显示正在使用该类型并且已添加importlib
以引用原始dll
library EnumDemo
{
// TLib : // TLib : : {D482D5CB-EE6C-455A-A28A-D26A5AC579D5}
importlib("StackOverflow.dll");
// TLib : mscorlib.dll : {BED7F4EA-1A96-11D2-8F08-00A0C9A6186D}
...
interface IEnumDemo : IDispatch {
[id(0x00000001), propget]
HRESULT Thing([out, retval] EThing* pRetVal);
[id(0x00000001), propput]
HRESULT Thing([in] EThing pRetVal);
};
...
答案 1 :(得分:1)