Partager via


Évaluer une expression espionne

Lorsque Visual Studio est prêt à afficher la valeur d'une expression espionne, il appelle IDebugExpression2 : : EvaluateSync qui appelle ensuite IDebugParsedExpression : : EvaluateSync. Il en résulte un objet d' IDebugProperty2 qui contient la valeur et le type de l'expression.

dans cette implémentation d' IDebugParsedExpression::EvaluateSync, l'expression est analysée et évaluée en même temps. cette implémentation effectue les tâches suivantes :

  1. Analyse et évalue l'expression pour produire un objet générique qui contient la valeur et son type. En c#, cela est représenté comme object en C++ cela est représenté comme VARIANT.

  2. Instancie une classe ( CValueProperty appelé par exemple) qui implémente l'interface d' IDebugProperty2 et stocker dans la classe la valeur à retourner.

  3. Retourne l'interface d' IDebugProperty2 de l'objet d' CValueProperty .

Code managé

Il s'agit d'une implémentation d' IDebugParsedExpression::EvaluateSync en code managé. La méthode d'assistance Tokenize analyse l'expression en une arborescence d'analyser. la fonction d'assistance EvalToken convertit le jeton à une valeur. La fonction d'assistance FindTerm parcourt de manière récursive l'arborescence d'analyser, en appelant EvalToken pour chaque nœud représentant une valeur et appliquant toutes les opérations (addition ou soustraction) dans l'expression.

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

Le code non managé

Il s'agit d'une implémentation d' IDebugParsedExpression::EvaluateSync dans du code non managé. La fonction d'assistance Evaluate analyse et évalue l'expression, en retournant VARIANT maintenant la valeur résultante. la fonction d'assistance VariantValueToProperty fournit avec VARIANT dans un objet d' CValueProperty .

[C++]
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;
}

Voir aussi

Concepts

Évaluer une expression de la fenêtre Espion

Exemple d'implémentation d'évaluation de l'expression