692 lines
28 KiB
C#
692 lines
28 KiB
C#
|
//----------------------------------------------------------------
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
//----------------------------------------------------------------
|
||
|
namespace System.Activities.Debugger
|
||
|
{
|
||
|
using System;
|
||
|
using System.Activities.XamlIntegration;
|
||
|
using System.Collections.Generic;
|
||
|
using System.ComponentModel;
|
||
|
using System.Diagnostics;
|
||
|
using System.Diagnostics.CodeAnalysis;
|
||
|
using System.Globalization;
|
||
|
using System.Linq;
|
||
|
using System.Linq.Expressions;
|
||
|
using System.Runtime;
|
||
|
using System.Windows.Markup;
|
||
|
using System.Xaml;
|
||
|
|
||
|
// Class to communicate with Workflow's Expression Evaluation.
|
||
|
// The methods of this class get invoked thru reflection by Visual Studio, so this needs to be public
|
||
|
// to allow partial trust to work.
|
||
|
public class DebugInfo
|
||
|
{
|
||
|
ActivityInstance activityInstance;
|
||
|
LocalInfo[] locals;
|
||
|
LocalInfo[] arguments;
|
||
|
Dictionary<string, LocalInfo> cachedLocalInfos;
|
||
|
|
||
|
internal DebugInfo(ActivityInstance activityInstance)
|
||
|
{
|
||
|
Fx.Assert(activityInstance != null, "activityInstance cannot be null");
|
||
|
this.activityInstance = activityInstance;
|
||
|
}
|
||
|
|
||
|
internal object EvaluateExpression(string expressionString)
|
||
|
{
|
||
|
// This is to shortcircuit a common case where
|
||
|
// internally, vsdebugger calls our EE with literal "0"
|
||
|
int intResult;
|
||
|
if (int.TryParse(expressionString, out intResult))
|
||
|
{
|
||
|
return intResult;
|
||
|
}
|
||
|
|
||
|
// At refresh, Expression Evaluator may re-evaluate locals/arguments.
|
||
|
// To speed up the process, locals/arguments are cached.
|
||
|
LocalInfo cachedLocalInfo = null;
|
||
|
if (this.cachedLocalInfos != null && this.cachedLocalInfos.TryGetValue(expressionString, out cachedLocalInfo))
|
||
|
{
|
||
|
return cachedLocalInfo;
|
||
|
}
|
||
|
|
||
|
Activity activity = activityInstance.Activity;
|
||
|
LocationReferenceEnvironment locationReferenceEnvironment = activity.PublicEnvironment;
|
||
|
|
||
|
// a temporary context for EvaluateExpression
|
||
|
// We're not using the executor so it's ok that it's null
|
||
|
CodeActivityContext context = new CodeActivityContext(activityInstance, null);
|
||
|
|
||
|
object result;
|
||
|
try
|
||
|
{
|
||
|
// First try as R-Value
|
||
|
if (!TryEvaluateExpression(expressionString, null, locationReferenceEnvironment, context, out result))
|
||
|
{
|
||
|
return SR.DebugInfoCannotEvaluateExpression(expressionString);
|
||
|
}
|
||
|
}
|
||
|
catch (Exception ex)
|
||
|
{
|
||
|
// ---- all exceptions, this exception is generated by user typing input in either
|
||
|
// Watch window or Immediate windows. Exception should not affect the current runtime.
|
||
|
// Except for fatal exception.
|
||
|
if (Fx.IsFatal(ex))
|
||
|
{
|
||
|
throw;
|
||
|
}
|
||
|
context.Dispose();
|
||
|
return SR.DebugInfoCannotEvaluateExpression(expressionString);
|
||
|
}
|
||
|
|
||
|
// Now try expression as an L-Value if possible.
|
||
|
try
|
||
|
{
|
||
|
object resultLocation;
|
||
|
if (TryEvaluateExpression(expressionString, result.GetType(), locationReferenceEnvironment, context, out resultLocation))
|
||
|
{
|
||
|
LocalInfo localInfo = new LocalInfo()
|
||
|
{
|
||
|
Name = expressionString,
|
||
|
Location = resultLocation as Location
|
||
|
};
|
||
|
this.cachedLocalInfos[expressionString] = localInfo;
|
||
|
return localInfo;
|
||
|
}
|
||
|
}
|
||
|
catch (Exception ex)
|
||
|
{
|
||
|
// ---- all exceptions, this exception is generated by user typing input in either
|
||
|
// Watch window or Immediate windows. Exception should not affect the current runtime.
|
||
|
// Except for fatal exception.
|
||
|
if (Fx.IsFatal(ex))
|
||
|
{
|
||
|
throw;
|
||
|
}
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
context.Dispose();
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
static bool TryEvaluateExpression(
|
||
|
string expressionString,
|
||
|
Type locationValueType, // Non null for Reference type (location)
|
||
|
LocationReferenceEnvironment locationReferenceEnvironment,
|
||
|
CodeActivityContext context,
|
||
|
out object result)
|
||
|
{
|
||
|
expressionString = string.Format(CultureInfo.InvariantCulture, "[{0}]", expressionString);
|
||
|
|
||
|
Type activityType;
|
||
|
if (locationValueType != null)
|
||
|
{
|
||
|
activityType = typeof(Activity<>).MakeGenericType(typeof(Location<>).MakeGenericType(locationValueType));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
activityType = typeof(Activity<object>);
|
||
|
}
|
||
|
|
||
|
// General expression.
|
||
|
ActivityWithResultConverter converter = new ActivityWithResultConverter(activityType);
|
||
|
ActivityWithResult expression = converter.ConvertFromString(
|
||
|
new TypeDescriptorContext { LocationReferenceEnvironment = locationReferenceEnvironment },
|
||
|
expressionString) as ActivityWithResult;
|
||
|
|
||
|
if (locationValueType != null)
|
||
|
{
|
||
|
Type locationHelperType = typeof(LocationHelper<>).MakeGenericType(locationValueType);
|
||
|
LocationHelper helper = (LocationHelper)Activator.CreateInstance(locationHelperType);
|
||
|
return helper.TryGetValue(expression, locationReferenceEnvironment, context, out result);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return TryEvaluateExpression(expression, locationReferenceEnvironment, context, out result);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static bool TryEvaluateExpression(
|
||
|
ActivityWithResult element,
|
||
|
LocationReferenceEnvironment locationReferenceEnvironment,
|
||
|
CodeActivityContext context,
|
||
|
out object result)
|
||
|
{
|
||
|
// value is some expression type and needs to be opened
|
||
|
context.Reinitialize(context.CurrentInstance, context.CurrentExecutor, element, context.CurrentInstance.InternalId);
|
||
|
if (element != null && !element.IsRuntimeReady)
|
||
|
{
|
||
|
WorkflowInspectionServices.CacheMetadata(element, locationReferenceEnvironment);
|
||
|
}
|
||
|
|
||
|
if (element == null || !element.IsFastPath)
|
||
|
{
|
||
|
result = SR.DebugInfoNotSkipArgumentResolution;
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
result = element.InternalExecuteInResolutionContextUntyped(context);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
internal LocalInfo[] GetArguments()
|
||
|
{
|
||
|
if (this.arguments == null || this.arguments.Length == 0)
|
||
|
{
|
||
|
this.arguments =
|
||
|
activityInstance.Activity.RuntimeArguments.Select(argument =>
|
||
|
new LocalInfo
|
||
|
{
|
||
|
Name = argument.Name,
|
||
|
Location = argument.InternalGetLocation(activityInstance.Environment)
|
||
|
}).ToArray();
|
||
|
|
||
|
if (this.arguments.Length > 0)
|
||
|
{
|
||
|
this.CacheLocalInfos(this.arguments);
|
||
|
}
|
||
|
}
|
||
|
return this.arguments;
|
||
|
}
|
||
|
|
||
|
internal LocalInfo[] GetLocals()
|
||
|
{
|
||
|
if (this.locals == null || this.locals.Length == 0)
|
||
|
{
|
||
|
Activity activity = activityInstance.Activity;
|
||
|
List<Variable> allVariables = new List<Variable>();
|
||
|
List<RuntimeArgument> allArguments = new List<RuntimeArgument>();
|
||
|
List<DelegateArgument> allDelegateArguments = new List<DelegateArgument>();
|
||
|
|
||
|
HashSet<string> existingNames = new HashSet<string>();
|
||
|
while (activity != null)
|
||
|
{
|
||
|
allVariables.AddRange(RemoveHiddenVariables(existingNames, activity.RuntimeVariables));
|
||
|
allVariables.AddRange(RemoveHiddenVariables(existingNames, activity.ImplementationVariables));
|
||
|
if (activity.HandlerOf != null)
|
||
|
{
|
||
|
allDelegateArguments.AddRange(RemoveHiddenDelegateArguments(existingNames,
|
||
|
activity.HandlerOf.RuntimeDelegateArguments.Select(delegateArgument =>
|
||
|
delegateArgument.BoundArgument)));
|
||
|
}
|
||
|
allArguments.AddRange(RemoveHiddenArguments(existingNames, activity.RuntimeArguments));
|
||
|
activity = activity.Parent;
|
||
|
}
|
||
|
|
||
|
this.locals =
|
||
|
new LocalInfo[] {
|
||
|
new LocalInfo
|
||
|
{
|
||
|
Name = "this",
|
||
|
Type = "System.Activities.ActivityInstance",
|
||
|
Value = activityInstance
|
||
|
}
|
||
|
}
|
||
|
.Concat(allVariables.Select(variable =>
|
||
|
new LocalInfo
|
||
|
{
|
||
|
Name = variable.Name,
|
||
|
Location = variable.InternalGetLocation(activityInstance.Environment)
|
||
|
})
|
||
|
.Concat(allArguments.Select(argument =>
|
||
|
new LocalInfo
|
||
|
{
|
||
|
Name = argument.Name,
|
||
|
Location = argument.InternalGetLocation(activityInstance.Environment)
|
||
|
}))
|
||
|
.Concat(allDelegateArguments.Select(argument =>
|
||
|
new LocalInfo
|
||
|
{
|
||
|
Name = argument.Name,
|
||
|
Location = argument.InternalGetLocation(activityInstance.Environment)
|
||
|
}))
|
||
|
.OrderBy(info => info.Name))
|
||
|
.ToArray();
|
||
|
|
||
|
if (this.locals.Length > 0)
|
||
|
{
|
||
|
this.CacheLocalInfos(this.locals);
|
||
|
}
|
||
|
}
|
||
|
return this.locals;
|
||
|
}
|
||
|
|
||
|
// Remove ancestor's variables that are hidden because the same name already define in the current scope.
|
||
|
// This will also update existingNames to include ancestor variable names that are retained.
|
||
|
static List<Variable> RemoveHiddenVariables(HashSet<string> existingNames, IEnumerable<Variable> ancestorVariables)
|
||
|
{
|
||
|
List<Variable> cleanUpList = new List<Variable>();
|
||
|
foreach (Variable variable in ancestorVariables)
|
||
|
{
|
||
|
if (variable.Name == null)
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (!(variable.Name.StartsWith("_", StringComparison.Ordinal) || // private variables that should be hidden
|
||
|
existingNames.Contains(variable.Name))) // variable name already exists in current scope
|
||
|
{
|
||
|
cleanUpList.Add(variable);
|
||
|
existingNames.Add(variable.Name);
|
||
|
}
|
||
|
}
|
||
|
return cleanUpList;
|
||
|
}
|
||
|
|
||
|
// Remove ancestor's arguments that are hidden because the same name already define in the current scope.
|
||
|
// This will also update existingNames to include ancestor delegate argument names that are retained.
|
||
|
static List<DelegateArgument> RemoveHiddenDelegateArguments(HashSet<string> existingNames, IEnumerable<DelegateArgument> ancestorDelegateArguments)
|
||
|
{
|
||
|
List<DelegateArgument> cleanUpList = new List<DelegateArgument>();
|
||
|
foreach (DelegateArgument delegateArgument in ancestorDelegateArguments)
|
||
|
{
|
||
|
if (delegateArgument != null && delegateArgument.Name != null)
|
||
|
{
|
||
|
if (!existingNames.Contains(delegateArgument.Name)) // variable name already exists in current scope
|
||
|
{
|
||
|
cleanUpList.Add(delegateArgument);
|
||
|
existingNames.Add(delegateArgument.Name);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return cleanUpList;
|
||
|
}
|
||
|
|
||
|
// Remove ancestor's arguments that are hidden because the same name already define in the current scope.
|
||
|
// This will also update existingNames to include ancestor argument names that are retained.
|
||
|
static List<RuntimeArgument> RemoveHiddenArguments(HashSet<string> existingNames, IList<RuntimeArgument> ancestorArguments)
|
||
|
{
|
||
|
List<RuntimeArgument> cleanUpList = new List<RuntimeArgument>(ancestorArguments.Count);
|
||
|
foreach (RuntimeArgument argument in ancestorArguments)
|
||
|
{
|
||
|
if (!existingNames.Contains(argument.Name))
|
||
|
{
|
||
|
cleanUpList.Add(argument);
|
||
|
existingNames.Add(argument.Name);
|
||
|
}
|
||
|
}
|
||
|
return cleanUpList;
|
||
|
}
|
||
|
|
||
|
internal bool SetValueAsString(Location location, string value, string stringRadix)
|
||
|
{
|
||
|
bool succeed = true;
|
||
|
try
|
||
|
{
|
||
|
value = value.Trim();
|
||
|
|
||
|
Type t = location.LocationType;
|
||
|
|
||
|
if (t == typeof(string) && value.StartsWith("\"", StringComparison.Ordinal) && value.EndsWith("\"", StringComparison.Ordinal))
|
||
|
{
|
||
|
location.Value = RemoveQuotes(value);
|
||
|
}
|
||
|
else if (t == typeof(bool))
|
||
|
{
|
||
|
location.Value = Convert.ToBoolean(value, CultureInfo.InvariantCulture);
|
||
|
}
|
||
|
else if (t == typeof(sbyte))
|
||
|
{
|
||
|
location.Value = Convert.ToSByte(RemoveHexadecimalPrefix(value), Convert.ToInt32(stringRadix, CultureInfo.InvariantCulture));
|
||
|
}
|
||
|
else if (t == typeof(char))
|
||
|
{
|
||
|
char ch;
|
||
|
succeed = ConvertToChar(value, Convert.ToInt32(stringRadix, CultureInfo.InvariantCulture), out ch);
|
||
|
if (succeed)
|
||
|
{
|
||
|
location.Value = ch;
|
||
|
}
|
||
|
}
|
||
|
else if (t == typeof(Int16))
|
||
|
{
|
||
|
location.Value = Convert.ToInt16(RemoveHexadecimalPrefix(value), Convert.ToInt32(stringRadix, CultureInfo.InvariantCulture));
|
||
|
}
|
||
|
else if (t == typeof(Int32))
|
||
|
{
|
||
|
location.Value = Convert.ToInt32(RemoveHexadecimalPrefix(value), Convert.ToInt32(stringRadix, CultureInfo.InvariantCulture));
|
||
|
}
|
||
|
else if (t == typeof(Int64))
|
||
|
{
|
||
|
location.Value = Convert.ToInt64(RemoveHexadecimalPrefix(value), Convert.ToInt32(stringRadix, CultureInfo.InvariantCulture));
|
||
|
}
|
||
|
else if (t == typeof(byte))
|
||
|
{
|
||
|
location.Value = Convert.ToByte(RemoveHexadecimalPrefix(value), Convert.ToInt32(stringRadix, CultureInfo.InvariantCulture));
|
||
|
}
|
||
|
else if (t == typeof(UInt16))
|
||
|
{
|
||
|
location.Value = Convert.ToUInt16(RemoveHexadecimalPrefix(value), Convert.ToInt32(stringRadix, CultureInfo.InvariantCulture));
|
||
|
}
|
||
|
else if (t == typeof(UInt32))
|
||
|
{
|
||
|
location.Value = Convert.ToUInt32(RemoveHexadecimalPrefix(value), Convert.ToInt32(stringRadix, CultureInfo.InvariantCulture));
|
||
|
}
|
||
|
else if (t == typeof(UInt64))
|
||
|
{
|
||
|
location.Value = Convert.ToUInt64(RemoveHexadecimalPrefix(value), Convert.ToInt32(stringRadix, CultureInfo.InvariantCulture));
|
||
|
}
|
||
|
else if (t == typeof(Single))
|
||
|
{
|
||
|
if (!value.Contains(","))
|
||
|
{
|
||
|
location.Value = Convert.ToSingle(value, CultureInfo.InvariantCulture);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
succeed = false;
|
||
|
}
|
||
|
}
|
||
|
else if (t == typeof(Double))
|
||
|
{
|
||
|
if (!value.Contains(","))
|
||
|
{
|
||
|
location.Value = Convert.ToDouble(value, CultureInfo.InvariantCulture);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
succeed = false;
|
||
|
}
|
||
|
}
|
||
|
else if (t == typeof(Decimal))
|
||
|
{
|
||
|
value = value.TrimEnd();
|
||
|
if (value.EndsWith("M", StringComparison.OrdinalIgnoreCase) || // suffix for Decimal format in C#
|
||
|
value.EndsWith("D", StringComparison.OrdinalIgnoreCase)) // suffix for Decimal format in VB
|
||
|
{
|
||
|
value = value.Substring(0, value.Length - 1); // remove the suffix
|
||
|
}
|
||
|
if (value.Contains(","))
|
||
|
{
|
||
|
succeed = false;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
location.Value = Convert.ToDecimal(value, CultureInfo.InvariantCulture);
|
||
|
}
|
||
|
}
|
||
|
else if (t == typeof(DateTime))
|
||
|
{
|
||
|
location.Value = Convert.ToDateTime(value, CultureInfo.CurrentCulture);
|
||
|
}
|
||
|
else if (t.IsEnum)
|
||
|
{
|
||
|
location.Value = Enum.Parse(t, value, true);
|
||
|
}
|
||
|
}
|
||
|
catch (InvalidCastException)
|
||
|
{
|
||
|
succeed = false;
|
||
|
}
|
||
|
catch (OverflowException)
|
||
|
{
|
||
|
succeed = false;
|
||
|
}
|
||
|
catch (FormatException)
|
||
|
{
|
||
|
succeed = false;
|
||
|
}
|
||
|
catch (ArgumentOutOfRangeException)
|
||
|
{
|
||
|
succeed = false;
|
||
|
}
|
||
|
return succeed;
|
||
|
}
|
||
|
|
||
|
// Cache local infos for faster evaluation.
|
||
|
void CacheLocalInfos(LocalInfo[] localInfos)
|
||
|
{
|
||
|
if (this.cachedLocalInfos == null)
|
||
|
{
|
||
|
this.cachedLocalInfos = new Dictionary<string, LocalInfo>(StringComparer.OrdinalIgnoreCase);
|
||
|
}
|
||
|
foreach (LocalInfo localInfo in localInfos)
|
||
|
{
|
||
|
this.cachedLocalInfos[localInfo.Name] = localInfo;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static string RemoveHexadecimalPrefix(string stringValue)
|
||
|
{
|
||
|
stringValue = stringValue.Trim().ToUpperInvariant();
|
||
|
if (stringValue.StartsWith("0X", StringComparison.Ordinal))
|
||
|
{
|
||
|
stringValue = stringValue.Substring(2);
|
||
|
}
|
||
|
return stringValue;
|
||
|
}
|
||
|
|
||
|
static string RemoveQuotes(string stringValue)
|
||
|
{
|
||
|
if (stringValue.StartsWith("\"", StringComparison.Ordinal))
|
||
|
{
|
||
|
stringValue = stringValue.Substring(1);
|
||
|
}
|
||
|
if (stringValue.EndsWith("\"", StringComparison.Ordinal))
|
||
|
{
|
||
|
stringValue = stringValue.Substring(0, stringValue.Length - 1);
|
||
|
}
|
||
|
return stringValue;
|
||
|
}
|
||
|
|
||
|
static bool ConvertToChar(string stringValue, int radix, out char ch)
|
||
|
{
|
||
|
bool succeed = false;
|
||
|
ch = '\0'; // null character
|
||
|
try
|
||
|
{
|
||
|
if ((stringValue[0] == '\'') || (stringValue[0] == '"')) // VB Char is using double quote
|
||
|
{
|
||
|
if (stringValue[1] == '\\')
|
||
|
{
|
||
|
switch (stringValue[2])
|
||
|
{
|
||
|
case '\'': // single quote
|
||
|
case 'a':
|
||
|
case 'b':
|
||
|
case 'f':
|
||
|
case 'n':
|
||
|
case 'r':
|
||
|
case 't':
|
||
|
case 'v':
|
||
|
if (stringValue[3] == stringValue[0]) // matched single/double quote
|
||
|
{
|
||
|
ch = stringValue[2];
|
||
|
}
|
||
|
succeed = true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else if (stringValue[2] == stringValue[0]) // matched single/double quote
|
||
|
{
|
||
|
ch = stringValue[1];
|
||
|
succeed = true;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{ // It can be either an digit , e.g. 65, or 65'A'.
|
||
|
// For the second case, we ignore the char.
|
||
|
int endIndex = stringValue.IndexOf('\'');
|
||
|
if (endIndex < 0)
|
||
|
{
|
||
|
endIndex = stringValue.IndexOf('"');
|
||
|
}
|
||
|
if (endIndex > 0)
|
||
|
{
|
||
|
stringValue = stringValue.Substring(0, endIndex);
|
||
|
}
|
||
|
ch = (char)Convert.ToUInt16(RemoveHexadecimalPrefix(stringValue), radix);
|
||
|
succeed = true;
|
||
|
}
|
||
|
}
|
||
|
catch (IndexOutOfRangeException)
|
||
|
{ // Invalid character length
|
||
|
succeed = false;
|
||
|
}
|
||
|
return succeed;
|
||
|
}
|
||
|
|
||
|
|
||
|
[SuppressMessage(FxCop.Category.Design, FxCop.Rule.NestedTypesShouldNotBeVisible, Justification = "Needed for partial trust.")]
|
||
|
internal class LocalInfo
|
||
|
{
|
||
|
string type;
|
||
|
object valueField;
|
||
|
[SuppressMessage(FxCop.Category.Design, FxCop.Rule.DoNotDeclareVisibleInstanceFields, Justification = "Needed for partial trust.")]
|
||
|
public string Name;
|
||
|
[SuppressMessage(FxCop.Category.Design, FxCop.Rule.DoNotDeclareVisibleInstanceFields, Justification = "Needed for partial trust.")]
|
||
|
public Location Location;
|
||
|
|
||
|
[SuppressMessage(FxCop.Category.Performance, FxCop.Rule.AvoidUncalledPrivateCode, Justification = "Called by Expression Evaluator")]
|
||
|
public object Value
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
if (this.Location != null)
|
||
|
{
|
||
|
return this.Location.Value;
|
||
|
}
|
||
|
return this.valueField;
|
||
|
}
|
||
|
set
|
||
|
{
|
||
|
this.valueField = value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[SuppressMessage(FxCop.Category.Performance, FxCop.Rule.AvoidUncalledPrivateCode, Justification = "Called by Expression Evaluator")]
|
||
|
public string Type
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
if (this.Location != null)
|
||
|
{
|
||
|
return this.Location.LocationType.Name;
|
||
|
}
|
||
|
return this.type;
|
||
|
}
|
||
|
set
|
||
|
{
|
||
|
this.type = value;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
class TypeDescriptorContext : ITypeDescriptorContext, IXamlNamespaceResolver, INameScope, INamespacePrefixLookup
|
||
|
{
|
||
|
public LocationReferenceEnvironment LocationReferenceEnvironment;
|
||
|
|
||
|
public IContainer Container
|
||
|
{
|
||
|
get { throw FxTrace.Exception.AsError(new NotImplementedException()); }
|
||
|
}
|
||
|
|
||
|
public object Instance
|
||
|
{
|
||
|
get { throw FxTrace.Exception.AsError(new NotImplementedException()); }
|
||
|
}
|
||
|
|
||
|
public PropertyDescriptor PropertyDescriptor
|
||
|
{
|
||
|
get { throw FxTrace.Exception.AsError(new NotImplementedException()); }
|
||
|
}
|
||
|
|
||
|
|
||
|
public void OnComponentChanged()
|
||
|
{
|
||
|
throw FxTrace.Exception.AsError(new NotImplementedException());
|
||
|
}
|
||
|
|
||
|
public bool OnComponentChanging()
|
||
|
{
|
||
|
throw FxTrace.Exception.AsError(new NotImplementedException());
|
||
|
}
|
||
|
|
||
|
public object GetService(Type serviceType)
|
||
|
{
|
||
|
if (serviceType.IsAssignableFrom(typeof(TypeDescriptorContext)))
|
||
|
{
|
||
|
return this;
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
|
||
|
public string GetNamespace(string prefix)
|
||
|
{
|
||
|
if (string.IsNullOrEmpty(prefix))
|
||
|
{
|
||
|
return String.Empty;
|
||
|
}
|
||
|
throw FxTrace.Exception.AsError(new NotImplementedException());
|
||
|
}
|
||
|
|
||
|
public object FindName(string name)
|
||
|
{
|
||
|
LocationReference result;
|
||
|
if (LocationReferenceEnvironment.TryGetLocationReference(name, out result))
|
||
|
{
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.VariableOrArgumentDoesNotExist(name)));
|
||
|
}
|
||
|
|
||
|
public void RegisterName(string name, object scopedElement)
|
||
|
{
|
||
|
throw FxTrace.Exception.AsError(new NotImplementedException());
|
||
|
}
|
||
|
|
||
|
public void UnregisterName(string name)
|
||
|
{
|
||
|
throw FxTrace.Exception.AsError(new NotImplementedException());
|
||
|
}
|
||
|
|
||
|
public string LookupPrefix(string name)
|
||
|
{
|
||
|
throw FxTrace.Exception.AsError(new NotImplementedException());
|
||
|
}
|
||
|
|
||
|
public IEnumerable<NamespaceDeclaration> GetNamespacePrefixes()
|
||
|
{
|
||
|
return Enumerable.Empty<NamespaceDeclaration>();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// to perform the generics dance around Locations we need these helpers
|
||
|
abstract class LocationHelper
|
||
|
{
|
||
|
public abstract bool TryGetValue(Activity expression, LocationReferenceEnvironment locationReferenceEnvironment, CodeActivityContext context, out object result);
|
||
|
}
|
||
|
|
||
|
class LocationHelper<TLocationValue> : LocationHelper
|
||
|
{
|
||
|
public override bool TryGetValue(Activity expression, LocationReferenceEnvironment locationReferenceEnvironment, CodeActivityContext context, out object result)
|
||
|
{
|
||
|
Activity<Location<TLocationValue>> activity = expression as Activity<Location<TLocationValue>>;
|
||
|
result = null;
|
||
|
if (activity != null)
|
||
|
{
|
||
|
context.Reinitialize(context.CurrentInstance, context.CurrentExecutor, expression, context.CurrentInstance.InternalId);
|
||
|
if (activity != null && !activity.IsRuntimeReady)
|
||
|
{
|
||
|
WorkflowInspectionServices.CacheMetadata(activity, locationReferenceEnvironment);
|
||
|
}
|
||
|
if (activity.IsFastPath)
|
||
|
{
|
||
|
result = activity.InternalExecuteInResolutionContext(context);
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|