COM Interop: что я должен сделать, чтобы свойство C # могло использоваться как VARIANT из VBA - PullRequest
8 голосов
/ 23 июня 2011

Допустим, у меня есть свойство C # Nullable DateTime?, которое необходимо использовать VBA через COM.

    public DateTime? TestDate {
        get ; set;
    }

К сожалению, Nullables не видны через COM, поэтому я хотел бы получить возвращаемое свойството, что будет рассматриваться как вариант от VBA.

К сожалению, я не уверен, как это должно быть написано.

Я попытался использовать object и dynamic вместо DateTime?: пока я могу получить значение свойства, Я не могу установить его (я получаю Ошибка времени выполнения '424' Требуется объект ошибки из VBA).

Примечание : у меня нет проблемс моей библиотекой COM Visible: все работает нормально, и я могу без проблем использовать типы .Net из VBA, за исключением этой конкретной проблемы.

Спасибо за любые указатели.

EDIT : Я нашел интересную страницу, описывающую маршалинг по умолчанию для объектов , но я не могу объяснить, почему я не могу установить свое свойство, если оно объявлено как object.
Я что-то упускаю.

Ответы [ 2 ]

8 голосов
/ 28 июня 2011

Вот что я сделал, чтобы обойти проблему.

Свойства объекта

public object MyObject {
    get ; set;
}

При использовании свойства .Net Object из VBA чтение свойства не является проблемой, и этобудет правильно рассматриваться как 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?

Теперь, чтобы сделать nullable 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 в качестве основыstore:

[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
0 голосов
/ 23 июня 2011

Создайте свой собственный класс NullableDateTime с такими функциями Nullable, как свойства HasValue и Value и метод GetValueOrDefault.

...