다음을 통해 공유


감시 표현식 평가

중요합니다

Visual Studio 2015에서는 식 계산기를 구현하는 이러한 방법이 더 이상 사용되지 않습니다. CLR 식 계산기 구현에 대한 자세한 내용은 CLR 식 계산기관리 식 계산기 샘플을 참조하세요.

Visual Studio가 조사식의 값을 표시할 준비가 되면 EvaluateSync를 호출하여, 이후 EvaluateSync를 연이어 호출합니다. 이 프로세스는 식의 값과 형식을 포함하는 IDebugProperty2 개체를 생성합니다.

이 구현 IDebugParsedExpression::EvaluateSync에서는 식이 구문 분석되고 동시에 평가됩니다. 이 구현은 다음 작업을 수행합니다.

  1. 식을 구문 분석하고 평가하여 값과 해당 형식을 보유하는 제네릭 개체를 생성합니다. C#에서는 이것이 object로 표시되고, C++에서는 이것이 VARIANT로 표시됩니다.

  2. CValueProperty 라는 클래스(이 예제에서는)를 인스턴스화하여 IDebugProperty2 인터페이스를 구현하고 반환할 값을 클래스에 저장합니다.

  3. CValueProperty 개체에서 IDebugProperty2 인터페이스를 반환합니다.

관리 코드

이는 관리 코드의 IDebugParsedExpression::EvaluateSync 구현입니다. 도우미 메서드 Tokenize 는 식을 구문 분석 트리로 변환합니다. 도우미 함수 EvalToken 는 토큰을 값으로 변환합니다. 도우미 함수 FindTerm 는 구문 분석 트리를 재귀적으로 트래버스하여 값을 나타내는 각 노드를 호출 EvalToken 하고 식에 작업(추가 또는 빼기)을 적용합니다.

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

관리되지 않는 코드

관리되지 않는 코드의 IDebugParsedExpression::EvaluateSync 구현입니다. 도우미 함수 Evaluate 는 식을 구문 분석하고 평가하여 결과 값을 보유하는 VARIANT 값을 반환합니다. 도우미 함수 VariantValueToPropertyVARIANTCValueProperty 개체로 번들로 묶습니다.

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