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::EvaluateSync
wyrażenia jest analizowane i oceniane w tym samym czasie. Ta implementacja wykonuje następujące zadania:
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 jakoVARIANT
element .Tworzy wystąpienie klasy (nazywanej
CValueProperty
w tym przykładzie), która implementujeIDebugProperty2
interfejs i przechowuje w klasie wartość, która ma zostać zwrócona.IDebugProperty2
Zwraca interfejs zCValueProperty
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;
}