С# взаимодействие — проверка существования объекта

Я хочу использовать COM-объект в своем приложении.
Как я могу убедиться, что объект зарегистрирован в машине?

Единственное решение, которое я нашел (также на SO) должен был использовать блок try-catch вокруг инициализации:

try {
    Foo.Bar COM_oObject = new Foo.Bar();
} catch (Exception ee) {
    // Something went wrong during init of COM object
}

Могу ли я сделать это каким-либо другим способом?
Я считаю неправильным реагировать на ошибку, ожидая ее и сообщая о ней, я бы предпочел заранее знать, что потерплю неудачу, и избежать ее.


person Dror    schedule 25.06.2009    source источник


Ответы (4)


Вы правильно используете обработку исключений: изящно выйти из конкретной ситуации, из которой вы знаете, как восстановиться.

В этом случае нет проблем с использованием try-catch, но вы могли бы, по крайней мере, поймать более конкретно: ComException.

person Dan    schedule 25.06.2009
comment
+1 за перехват конкретного исключения, особенно за однострочный вызов хорошо документированного и стабильного API. - person Daniel Earwicker; 25.06.2009
comment
Итак, вы имеете в виду, что нет способа (вы знаете) избежать исключений в случае, когда объект не установлен? - person Dror; 30.06.2009

«Я считаю неправильным иметь дело с ошибкой, ожидая ее и сообщая о ней»

Разве это не цель try-catch? Кстати, исключение возникает, когда произошло что-то действительно плохое, и поскольку это довольно плохо, что COM-объект, на который вы ссылаетесь, не зарегистрирован, поэтому исключение является идеальным решением. И вы не можете обработать исключение каким-либо другим способом.

Я думаю, что это правильный способ сделать это.

person Aamir    schedule 25.06.2009
comment
Исключения обходятся дорого (см. codeproject.com/KB/dotnet/When_to_use_exceptions.aspx). ) - ищу способ получше, если не найду, буду доволен существующим кодом. - person Dror; 25.06.2009

Если вы знаете ProgId вашего компонента. Вы можете попробовать этот трюк

comType = Type.GetTypeFromProgID(progID,true/*throw on error*/);
person Sergey Mirvoda    schedule 25.06.2009

Если вы часто делаете это и хотите, чтобы у вас был эквивалент броска без исключений, попробуйте:

public static class Catching<TException> where TException : Exception
{
    public static bool Try<T>(Func<T> func, out T result)
    {
        try
        {
            result = func();
            return true;
        }
        catch (TException x) 
        {
            // log exception message (with call stacks 
            // and all InnerExceptions)
        }

        result = default(T);
        return false;
    }

    public static T Try<T>(Func<T> func, T defaultValue)
    {
        T result;
        if (Try(func, out result))
            return result;

        return defaultValue;
    }
}

Итак, теперь вы можете сделать это:

Foo.Bar newObj;
if (!Catching<ComException>.Try(() => new Foo.Bar(), out newObj))
{
    // didn't work.
}

Или, если у вас есть объект по умолчанию, хранящийся в defaultMyInterface, вы бы использовали его для реализации интерфейса, если нет ничего лучше:

IMyInterface i = Catching<ComException>.Try(() => new Foo.Bar() as IMyInterface,
                                            defaultMyInterface);

Вы также можете сделать это в совершенно другом сценарии:

int queueSize = Catching<MyParsingException>
    .Try(() => Parse(optionStr, "QueueSize"), 5);

Если Parse выдает MyParsingException, queueSize по умолчанию будет 5, в противном случае используется возвращаемое значение из Parse (или любое другое исключение будет распространяться нормально, что обычно требуется при неожиданном исключении).

Это помогает избежать прерывания потока кода, а также централизует политику ведения журналов.

person Daniel Earwicker    schedule 25.06.2009