Как я должен написать правильный код COM? - PullRequest
1 голос
/ 20 сентября 2011

Следующий код освобождает все правильно, но выглядит ужасно. Как мне написать COM-код, который не пропускает ссылки и доступен для чтения?

Игнорировать биты C ++ \ CLI.

IBaseFilter* leftFilter;
if (graph->FindFilterByName(L"Left", &leftFilter) == S_OK)
{
    IPin* leftIn;
    if (leftFilter->FindPin(L"Audio Input pin (rendered)", &leftIn) == S_OK)
    {
        IBaseFilter* meterFilter;
        if (graph->FindFilterByName(L"Meter", &meterFilter) == S_OK)
        {
            IPin* meterIn;
            if (meterFilter->FindPin(L"Input", &meterIn) == S_OK)
            {
                IPin* meterOut;
                if (meterFilter->FindPin(L"Output", &meterOut) == S_OK)
                {
                    try
                    {
                        IntPtr fileName = Marshal::StringToCoTaskMemUni(source->OriginalString);
                        IBaseFilter* sourceFilter;
                        if (graph->AddSourceFilter((LPCWSTR)(void*)fileName, L"Source", &sourceFilter) == S_OK)
                        {
                            IPin* sourceOut;
                            if (sourceFilter->FindPin(L"Output", &sourceOut) == S_OK)
                            {
                                if (graph->Connect(sourceOut, meterIn) == S_OK)
                                {
                                    IBaseFilter* rightFilter;
                                    if (graph->FindFilterByName(L"Right", &rightFilter) == S_OK)
                                    {
                                        IPin* rightIn;
                                        if (rightFilter->FindPin(L"Audio Input pin (rendered)", &rightIn) == S_OK)
                                        {
                                            IBaseFilter* splitFilter;
                                            if (graph->FindFilterByName(L"Split", &splitFilter) == S_OK)
                                            {
                                                IPin* splitIn;
                                                if (splitFilter->FindPin(L"Input", &splitIn) == S_OK)
                                                {
                                                    IPin* splitLeft;
                                                    if (splitFilter->FindPin(L"Left", &splitLeft) == S_OK)
                                                    {
                                                        IPin* splitRight;
                                                        if (splitFilter->FindPin(L"Right", &splitRight) == S_OK)
                                                        {
                                                            if (graph->ConnectDirect(meterOut, splitIn, NULL) == S_OK
                                                                && graph->ConnectDirect(splitLeft, leftIn, NULL) == S_OK
                                                                && graph->ConnectDirect(splitRight, rightIn, NULL) == S_OK)
                                                            {
                                                                this->source = source;
                                                                OnMediaOpened(EventArgs::Empty);
                                                            }
                                                            splitRight->Release();
                                                        }
                                                        splitLeft->Release();
                                                    }
                                                    splitIn->Release();
                                                }
                                                splitFilter->Release();
                                            }
                                            rightIn->Release();
                                        }
                                        rightFilter->Release();
                                    }
                                    else
                                    {
                                        if (graph->ConnectDirect(meterOut, leftIn, NULL) == S_OK)
                                        {
                                            this->source = source;
                                            OnMediaOpened(EventArgs::Empty);
                                        }
                                    }
                                }
                                sourceOut->Release();
                            }
                            sourceFilter->Release();
                        }
                        Marshal::FreeCoTaskMem(fileName);
                    }
                    catch (Exception^) { }
                    meterOut->Release();
                }
                meterIn->Release();
            }
            meterFilter->Release();
        }
        leftIn->Release();
    }
    leftFilter->Release();
}

Ответы [ 4 ]

2 голосов
/ 20 сентября 2011

Используйте умный указатель, чтобы бросить все Release() с, а затем используйте неудачу, а не успех, как условие.

if (graph->FindFilterByName(L"Left", &leftFilter) != S_OK)
    throw ...;

Конечно, это может быть преобразовано в вашу любимую встроенную функцию илимакросъемки.

2 голосов
/ 20 сентября 2011

Используйте умный указатель, такой как CComPtr . Документация MSDN по CComPtr содержит пример, показывающий, как CComPtr упрощает работу по сравнению с ручным управлением временем жизни.

1 голос
/ 20 сентября 2011

Вы можете использовать своего рода умный указатель, который вызовет Release для вас в деструкторе. Например, CComPtr или навязчивый указатель Буста .

0 голосов
/ 20 сентября 2011

Использование boost::intrusive_ptr приведет к вызову всех этих вызовов на Release.Я не могу придумать другой способ удалить все эти вложенные if s, но с помощью функций, генерирующих исключения.Подумайте о том, чтобы окружить ваши вызовы функций чем-то, что проверяет на S_OK или на throw с.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...