在.NET中为Interop公开属性作为变体

Mat*_*lko 8 c# vb.net com properties com-interop

我正在.NET中创建一个包装类(VB.NET,因为它发生但与C#同样相关),它暴露给COM,我试图包装的一个属性是Variant.我以为我只能使用一个Object,但是我收到一个错误:

Public Property FieldValue([vFieldID As Object = -1]) As Object不能作为属性'让'暴露给COM.您将无法使用"Let"语句从Visual Basic 6.0为此属性分配非对象值(如数字或字符串).*

我的财产声明如下:

Public Property FieldValue(Optional ByVal vFieldID As Object = -1) As Object
    Get
        Return _objVAccess.FieldValue(vFieldID)
    End Get
    Set(ByVal value As Object)
        _objVAccess.FieldValue = value
    End Set
End Property
Run Code Online (Sandbox Code Playgroud)

我的属性实际上从数据库返回一个值,可以是整数,字符串,日期等,因此它不是 COM方面的对象.是否有任何解决方法允许属性让?

Han*_*ant 32

COM Automation支持默认属性,该属性具有dispid 0.这在VB6代码中使用效果很好,生成非常紧凑的代码.一个典型的例子是:

rs!Customer = "foo"
Run Code Online (Sandbox Code Playgroud)

这是语法糖:

rs.Fields.Item("Customer").Value = "foo"
Run Code Online (Sandbox Code Playgroud)

此处使用了三个默认属性,但未在原始语句中进行命名.Recordset接口将Fields属性作为默认属性,生成Fields接口引用.其中Item属性作为默认(索引)属性,生成Field接口引用.其中Value属性作为默认属性,生成变体.

哪个非常好.然而,像这样的极端语法糖的价格是蛀牙.在语句中存在语法歧义,例如:

Dim obj  
obj = someObject
Run Code Online (Sandbox Code Playgroud)

这是什么意思?是否要将someObject引用分配给obj?或者您想要分配someObject 的默认属性?非常不同的东西,obj类型将完全不同.这是在VB6中使用Set关键字解决的.如果要分配对象引用,则必须编写:

Set obj = someObject
Run Code Online (Sandbox Code Playgroud)

如果您要分配默认属性值,则省略Set或use Let.这很令人讨厌,并且很长一段时间困扰着新手Visual Basic和VB脚本程序员.

COM Automation通过允许属性具有两个 setter 来实现此功能.IDL中的propputpropputref分别是propputref是指定对象的那个.您还可以在IDispatch定义中看到这一点,IDispatch :: Invoke()方法使用DISPATCH_PROPERTYPUT和DISPATCH_PROPERTYPUTREF区分两者.

向前推进到VB.NET,微软认为模糊性太痛苦并且消除了默认的非索引属性的概念.哪个幸福也退休了Set关键字.然而,这会产生一个新问题,没有任何方法可以编写一个[ComVisible]类,它可以具有Object类型的属性,并且具有接受对象引用的setter.语言语法只允许一个setter,CLR中的COM interop层缺少合成两个的管道.值得注意的是,这只是一个警告,你仍然得到了propput setter,你只是不会得到propputref setter.据我所知,这就是你想要的.

在VB6虚拟类中定义接口,或者通过显式写入IDL并使用midl.exe编译它确实是一种绕过警告的方法.如约翰里瓦德在这个问题中所示.