Udostępnij za pośrednictwem


Ocena wyrażenia zegarka

Ważne

W programie Visual Studio 2015 ten sposób implementowania ewaluatorów wyrażeń jest przestarzały. Aby uzyskać informacje na temat implementowania ewaluatorów wyrażeń CLR, zobacz clR expression evaluators and Managed expression evaluator sample (Przykład ewaluatora wyrażeń zarządzanych).

Gdy program Visual Studio jest gotowy do wyświetlenia wartości wyrażenia zegarka, wywołuje metodę EvaluateSync, która z kolei wywołuje metodę EvaluateSync. Ten proces tworzy obiekt IDebugProperty2 zawierający wartość i typ wyrażenia.

W tej implementacji IDebugParsedExpression::EvaluateSyncwyrażenia jest analizowane i oceniane w tym samym czasie. Ta implementacja wykonuje następujące zadania:

  1. Analizuje i ocenia wyrażenie w celu utworzenia obiektu ogólnego, który zawiera wartość i jego typ. W języku C#jest to reprezentowane jako element object w języku C++, który jest reprezentowany jako VARIANTelement .

  2. Tworzy wystąpienie klasy (nazywanej CValueProperty w tym przykładzie), która implementuje IDebugProperty2 interfejs i przechowuje w klasie wartość, która ma zostać zwrócona.

  3. IDebugProperty2 Zwraca interfejs z CValueProperty obiektu .

Kod zarządzany

Jest to implementacja kodu zarządzanego IDebugParsedExpression::EvaluateSync . Metoda Tokenize pomocnika analizuje wyrażenie w drzewie analizy. Funkcja EvalToken pomocnika konwertuje token na wartość. Funkcja FindTerm pomocnika rekursywnie przechodzi przez drzewo analizy, wywołując EvalToken dla każdego węzła reprezentującego wartość i stosując dowolne operacje (dodawanie lub odejmowanie) w wyrażeniu.

namespace EEMC
{
    public class CParsedExpression : IDebugParsedExpression
    {
        public HRESULT EvaluateSync(
            uint evalFlags,
            uint timeout,
            IDebugSymbolProvider provider,
            IDebugAddress address,
            IDebugBinder binder,
            string resultType,
            out IDebugProperty2 result)
        {
            HRESULT retval = COM.S_OK;
            this.evalFlags = evalFlags;
            this.timeout = timeout;
            this.provider = provider;
            this.address = address;
            this.binder = binder;
            this.resultType = resultType;

            try
            {
                IDebugField field = null;
                // Tokenize, then parse.
                tokens = Tokenize(expression);
                result = new CValueProperty(
                        expression,
                        (int) FindTerm(EvalToken(tokens[0], out field),1),
                        field,
                        binder);
            }
            catch (ParseException)
            {
                result = new CValueProperty(expression, "Huh?");
                retval = COM.E_INVALIDARG;
            }
            return retval;
        }
    }
}

Niezarządzany kod

Jest to implementacja IDebugParsedExpression::EvaluateSync kodu niezarządzanego. Funkcja Evaluate pomocnika analizuje i oblicza wyrażenie, zwracając przytrzymanie VARIANT wartości wynikowej. Funkcja VariantValueToProperty pomocnika umieszcza element w VARIANT CValueProperty obiekcie .

STDMETHODIMP CParsedExpression::EvaluateSync(
    in  DWORD                 evalFlags,
    in  DWORD                 dwTimeout,
    in  IDebugSymbolProvider* pprovider,
    in  IDebugAddress*        paddress,
    in  IDebugBinder*         pbinder,
    in  BSTR                  bstrResultType,
    out IDebugProperty2**     ppproperty )
{
    // dwTimeout parameter is ignored in this implementation.
    if (pprovider == NULL)
        return E_INVALIDARG;

    if (paddress == NULL)
        return E_INVALIDARG;

    if (pbinder == NULL)
        return E_INVALIDARG;

    if (ppproperty == NULL)
        return E_INVALIDARG;
    else
        *ppproperty = 0;

    HRESULT hr;
    VARIANT value;
    BSTR    bstrErrorMessage = NULL;
    hr = ::Evaluate( pprovider,
                     paddress,
                     pbinder,
                     m_expr,
                     &bstrErrorMessage,
                     &value );
    if (hr != S_OK)
    {
        if (bstrErrorMessage == NULL)
            return hr;

        //we can display better messages ourselves.
        HRESULT hrLocal = S_OK;
        VARIANT varType;
        VARIANT varErrorMessage;

        VariantInit( &varType );
        VariantInit( &varErrorMessage );
        varErrorMessage.vt      = VT_BSTR;
        varErrorMessage.bstrVal = bstrErrorMessage;

        CValueProperty* valueProperty = new CValueProperty();
        if (valueProperty != NULL)
        {
            hrLocal = valueProperty->Init(m_expr, varType, varErrorMessage);
            if (SUCCEEDED(hrLocal))
            {
                hrLocal = valueProperty->QueryInterface( IID_IDebugProperty2,
                        reinterpret_cast<void**>(ppproperty) );
            }
        }

        VariantClear(&varType);
        VariantClear(&varErrorMessage); //frees BSTR
        if (!valueProperty)
            return hr;
        valueProperty->Release();
        if (FAILED(hrLocal))
            return hr;
    }
    else
    {
        if (bstrErrorMessage != NULL)
            SysFreeString(bstrErrorMessage);

        hr = VariantValueToProperty( pprovider,
                                     paddress,
                                     pbinder,
                                     m_radix,
                                     m_expr,
                                     value,
                                     ppproperty );
        VariantClear(&value);
        if (FAILED(hr))
            return hr;
    }

    return S_OK;
}