2012-04-20 2 views
2

Я пишу COM-оболочки, которые возвращают объект, или null, если объект не существует. При вызове из VBScript, возвращая нуль кидает ошибку "Требуется объект: '' ComObj.Prop2" Код 800A01A8 ...C# COM Interop возвращающий объект нулевых причин 0x800A01A8 Требуемый объект

C#

public class testCOM 
{ 
    public object Func(int i) 
    { 
     if (i == 1) return new object(); 
     if (i == 2) return DBNull.Value; 
     return null; 
    } 
} 

VBScript

set ComObj = CreateObject("ClassLibrary1.testCOM") 

set TestObj = ComObj.Func(1) 'This Works 
set TestObj = ComObj.Func(2) 'Throws "Object required: 'ComObj.Func(...)'" Code 800A01A8 
set TestObj = ComObj.Func(3) 'Throws "Object required: 'ComObj.Func(...)'" Code 800A01A8 
set TestObj = Nothing  'This is what I want to occur with Func(2) and Func(3) 

Я попытался возвращение DBNull. Значение, которое предполагается маршалировать как VT_NULL, но не повезло ...

Я действительно не хочу писать объект-обертку, похожий на Nullabe <> с .HasValue и .Val у.е ... Еще один вариант мне не нравится, чтобы создать объект Nothing (внутри нет пространства имен), так что я могу сделать:

If TestObj Is Nothing And TestObj = "Nothing" Then 
    'TestObj was nothing or "Nothing" 
End If 

Если я использую объект Nothing, то мой COM объект должен reutrn типа Object вместо ожидаемого типизированного объекта, что делает код более сложным для чтения, хотя функционально то же самое для моих целей.

Каков наилучший способ возврата нулевого объекта в VBScript через COM?

ответ

0

Проверьте подпись на своем интерфейсе и убедитесь, что она правильная. Если бы я сделать следующее:

public object test(int i) { 
    object retval = null; 
    if (i == 1) { 
     retval = new Object(); 
    } else if (i == 2) { 
     retval = DBNull.Value; 
    } 
    return retval; 
} 

с интерфейсом подписью:

[DispId(1001)] 
object test(int i); 

, а затем, в VBScript, сделайте следующее:

' myObject is my instantiated COM class 
WScript.Echo TypeName(myObject.test(1)) 
WScript.Echo TypeName(myObject.test(2)) 
WScript.Echo TypeName(myObject.test(3)) 

я вернусь:

Object 
Null 
Empty 
+0

Я ценю ответ. К сожалению, ваше предложение не присваивает возвращаемый объект/значение переменной. Вместо этого он передает его непосредственно другой функции TypeName. Если ваш vbscript был: – FuncL

+0

Если ваш vbscript попытался «установить TestObj = myObject.test (2)», чтобы «Echo TypeName (TestObj)», он ошибся с кодом 800A01A8. По-видимому, 'set' требует, чтобы объект был установлен, поэтому я не могу вернуть значение null, которое не является объектом. Если вы оставите «набор», он будет работать. Я прибегал к созданию класса Nothing в корневом пространстве имен и тестировании 'If TypeName (TestObj) =« Nothing »Then' – FuncL

+0

Не могли бы вы просто протестировать с IsNull, прежде чем пытаться установить его? – basiphobe

0

Добавление маршала помогает:

[return:MarshalAs(UnmanagedType.IDispatch)] 
public object Func(int i) 
{ 
    if (i == 1) return new object(); 
    if (i == 2) return DBNull.Value; 
    return null; 
} 

Я не уверен, почему. И если у вас есть интерфейс, этот атрибут должен применяться на уровне интерфейса.