Freigeben über


Auswerten eines Überwachungsausdrucks

Von Bedeutung

In Visual Studio 2015 ist diese Methode der Implementierung von Ausdrucksvaluatoren veraltet. Informationen zur Implementierung von CLR-Ausdrucksauswertern finden Sie unter CLR-Ausdrucksauswerter und Beispiel für verwaltete Ausdrucksauswerter.

Wenn Visual Studio bereit ist, den Wert eines Watch-Ausdrucks anzuzeigen, ruft es EvaluateSync auf, das wiederum EvaluateSync aufruft. Dieser Prozess erzeugt ein IDebugProperty2 -Objekt, das den Wert und typ des Ausdrucks enthält.

In dieser Implementierung IDebugParsedExpression::EvaluateSyncwird der Ausdruck analysiert und gleichzeitig ausgewertet. Diese Implementierung führt die folgenden Aufgaben aus:

  1. Analysiert und wertet den Ausdruck aus, um ein generisches Objekt zu erzeugen, das den Wert und seinen Typ enthält. In C# wird dies als object dargestellt, während es in C++ als VARIANT dargestellt wird.

  2. Instanziiert eine Klasse (im Beispiel CValueProperty genannt), die die Schnittstelle IDebugProperty2 implementiert und den Wert speichert, der zurückgegeben werden soll.

  3. Gibt die IDebugProperty2 Schnittstelle aus dem CValueProperty Objekt zurück.

Verwalteter Code

Dies ist eine Implementierung von IDebugParsedExpression::EvaluateSync in verwaltetem Code. Die Hilfsmethode Tokenize analysiert den Ausdruck in einen Syntaxbaum. Die Hilfsfunktion EvalToken konvertiert das Token in einen Wert. Die Hilfsfunktion FindTerm durchläuft rekursiv die Analysestruktur und ruft EvalToken für jeden Knoten, der einen Wert darstellt, und wendet alle Vorgänge (Addition oder Subtraktion) im Ausdruck an.

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;
        }
    }
}

Nicht verwalteter Code

Dies ist eine Implementierung des IDebugParsedExpression::EvaluateSync in nicht verwaltetem Code. Die Hilfsfunktion Evaluate analysiert und wertet den Ausdruck aus und gibt einen VARIANT Haltewert für den resultierenden Wert zurück. Die Hilfsfunktion VariantValueToProperty bündelt das VARIANT Objekt in ein CValueProperty Objekt.

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;
}