COM互操作:我应该怎么做才能使C#属性可以作为VBA中的VARIANT使用



假设我有一个C#可为Null的DateTime?属性,VBA需要通过COM.使用该属性

    public DateTime? TestDate {
        get ; set;
    }

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

不幸的是,我不知道该怎么写。

我尝试使用objectdynamic而不是DateTime?:虽然我可以获得属性值,但我无法设置它(我从VBA中获得运行时错误'424'所需对象错误)。

注意:我在使我的库COM可见方面没有问题:一切都很好,我可以使用。网络类型从VBA没有问题,除了这个特殊的问题。

谢谢你的指点。

EDIT:我发现了一个有趣的页面,描述了对象的默认编组,但我似乎无法解释为什么如果属性声明为object,我就不能设置它
我错过了什么。

下面是我为解决这个问题所做的工作。

对象属性

public object MyObject {
    get ; set;
}

使用时。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的问题。网

日期时间

现在,为了使可为null的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

创建自己的NullableDateTime类,该类具有Nullable特性,如HasValueValue属性以及GetValueOrDefault方法。

最新更新