Compartir a través de


Evaluar una expresión en observación

Importante

En Visual Studio 2015, esta forma de implementar evaluadores de expresiones está en desuso. Para obtener información sobre la implementación de evaluadores de expresiones CLR, consulte Evaluadores de expresiones CLR y Ejemplo de evaluador de expresiones administradas.

Cuando Visual Studio está listo para mostrar el valor de una expresión de inspección, llama a EvaluateSync, que a su vez llama a EvaluateSync. Este proceso genera un objeto IDebugProperty2 que contiene el valor y el tipo de la expresión.

En esta implementación de IDebugParsedExpression::EvaluateSync, la expresión se analiza y evalúa al mismo tiempo. Esta implementación realiza las siguientes tareas:

  1. Analiza y evalúa la expresión para generar un objeto genérico que contiene el valor y su tipo. En C#, esto se representa como un object, mientras que en C++, se representa como un VARIANT.

  2. Crea una instancia de una clase (denominada CValueProperty en este ejemplo) que implementa la IDebugProperty2 interfaz y almacena en la clase el valor que se va a devolver.

  3. Devuelve la IDebugProperty2 interfaz del CValueProperty objeto .

Código administrado

Se trata de una implementación de IDebugParsedExpression::EvaluateSync en código administrado. El método Tokenize auxiliar analiza la expresión en un árbol de análisis. La función EvalToken auxiliar convierte el token en un valor. La función FindTerm auxiliar recorre recursivamente el árbol de análisis, llamando EvalToken a para cada nodo que representa un valor y aplicando cualquier operación (suma o resta) en la expresión.

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

Código no administrado

Se trata de una implementación de IDebugParsedExpression::EvaluateSync en código no administrado. La función auxiliar Evaluate parsea y evalúa la expresión, devolviendo un VARIANT que contiene el valor resultante. La función VariantValueToProperty auxiliar agrupa el objeto VARIANT en un CValueProperty objeto .

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