gpt4 book ai didi

c# - COM 互操作 : What should I do to make a C# property usable as a VARIANT from VBA

转载 作者:太空狗 更新时间:2023-10-29 18:32:58 26 4
gpt4 key购买 nike

假设我有一个 C# Nullable DateTime? 属性需要 VBA 通过 COM 使用。

    public DateTime? TestDate {
get ; set;
}

不幸的是,Nullables 在 COM 中是不可见的,所以我想让该属性返回一个在 VBA 中将被视为 Variant 的东西。

不幸的是,我不确定这应该怎么写。

我尝试使用 objectdynamic 而不是 DateTime?:虽然我可以获得属性值,但我无法设置它(我从 VBA 得到 Run-Time error '424' Object required 错误)。

注意:我没有让我的库 COM 可见的问题:一切正常,我可以毫无问题地使用 VBA 中的 .Net 类型,除了这个特殊问题。

感谢您的指点。

编辑:我发现一个有趣的页面描述了 default marshalling for objects ,但我似乎无法解释为什么我不能设置我的属性,如果它被声明为 object
我错过了一些东西。

最佳答案

这是我为解决该问题所做的工作。

对象属性

public object MyObject {
get ; set;
}

当从 VBA 使用 .Net Object 属性时,读取该属性没有问题,它会被正确地视为一个 Variant
不幸的是,尝试从 VBA 设置属性将失败。

但是,使用简单的方法就可以正常工作:

private object _MyObject;

public object GetMyObject() {
return _MyObject;
}

public void SetMyObject(object value) {
if (value == DbNull.Value)
value = null;
_MyObject = value;
}

检查 DBNull 是为了解决 VBA 的 Null 实际上被编码为 DBNull 到 .Net 的问题。

日期时间?

现在,要使可为空的 DateTime? 起作用,我们可以执行以下操作:

private DateTime? _MyDate;

public object GetMyDate() {
return _MyDate
}

public void SetMyDate(object value) {
if (value == null || value == DbNull.Value)
_MyDate = null;
else
_MyDate = (DateTime?)value;
}

并且在 VBA 中,我们可以将这些 get/set 隐藏在属性中(假设我们在 myclassinstance 中有一个现有的类实例):

Public Property Get MyDate() As Variant
MyDate = myclassinstance.GetMyDate()
End Property

Public Property Set MyDate(value as Variant)
myclassinstance.SetMyDate value
End Property

更通用的方式

这有点难看,因为我们的 C# 类将 MyDate 公开为 GetMyDate/SetMyDate 方法而不是属性。
为了以更通用的方式实现这一点,以便该机制可用于我们类中的所有属性,我们可以使用 Dictionary 作为后备存储:

[ClassInterface(ClassInterfaceType.AutoDual)]
[ComVisible(true)]
public class MyClass {

private Dictionary<string,object> backingStore = new Dictionary<string,object>();

public object GetPropertyValue(string propertyName) {
if (backingStore.ContainsKey(propertyName))
return backingStore[propertyName];
else
return null
}

public void SetPropertyValue(string propertyName, object value) {
if (value == DBNull.Value) value = null;
if (backingStore.ContainsKey(propertyName))
backingStore[propertyName] = value;
else
backingStore.Add(propertyName, value);
}

[ComVisible(false)]
public DateTime? MyDate {
get {
return GetPropertyValue(@"MyDate") ?? default(DateTime?);
}
set {
SetPropertyValue(@"MyDate", value);
}
}
}

ComVisible(false) 属性确保属性在 VBA 中不可见。

在 VBA 中,我们声明属性:

Public Property Get MyDate() As Variant
MyDate = myclassinstance.GetPropertyValue("MyDate")
End Property

Public Property Set MyDate(value as Variant)
myclassinstance.SetPropertyValue "MyDate", value
End Property

关于c# - COM 互操作 : What should I do to make a C# property usable as a VARIANT from VBA,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6453625/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com