public override bool TryMorphExpression(ActivityWithResult expression, bool isLocationExpression, Type newType, EditingContext context, out ActivityWithResult newExpression) { Fx.Assert(expression != null, "Original expression shouldn't be null in morph helper"); Fx.Assert(context != null, "EditingContext shouldn't be null in morph helper"); newExpression = null; if (expression.ResultType == newType && (ExpressionHelper.IsGenericLocationExpressionType(expression) == isLocationExpression)) { newExpression = expression; return true; } if (context != null) { string expressionEditor = ExpressionHelper.GetRootEditorSetting(context.Services.GetService<ModelTreeManager>(), WorkflowDesigner.GetTargetFramework(context)); ParserContext parserContext = new ParserContext(); string expressionText = ExpressionHelper.GetExpressionString(expression, parserContext); if (!string.IsNullOrEmpty(expressionEditor)) { return ExpressionTextBox.TryConvertFromString(expressionEditor, expressionText, isLocationExpression, newType, out newExpression); } } return false; }
internal static string GetExpressionString(Activity expression, ParserContext context) { string expressionString = null; if (expression != null) { Type expressionType = expression.GetType(); Type expressionArgumentType = expressionType.IsGenericType ? expressionType.GetGenericArguments()[0] : typeof(object); bool isLiteral = expressionType.IsGenericType ? Type.Equals(typeof(Literal<>), expressionType.GetGenericTypeDefinition()) : false; //handle ITextExpression if (expression is ITextExpression) { ITextExpression textExpression = expression as ITextExpression; expressionString = textExpression.ExpressionText; } //handle Literal Expression else if (isLiteral) { TypeConverter converter = XamlUtilities.GetConverter(expressionArgumentType); if (converter != null && converter.CanConvertTo(context, typeof(string))) { PropertyInfo literalValueProperty = expressionType.GetProperty("Value"); Fx.Assert(literalValueProperty != null && literalValueProperty.GetGetMethod() != null, "Literal<T> must have the Value property with a public get accessor."); object literalValue = literalValueProperty.GetValue(expression, null); string convertedString = null; if (literalValue != null) { try { convertedString = converter.ConvertToString(context, literalValue); } catch (ArgumentException) { convertedString = literalValue.ToString(); } } expressionString = expressionArgumentType == typeof(string) ? ("\"" + convertedString + "\"") : convertedString; } } else if (expressionType.IsGenericType && (expressionType.GetGenericTypeDefinition() == typeof(VariableValue<>) || expressionType.GetGenericTypeDefinition() == typeof(VariableReference<>))) { PropertyInfo variableProperty = expression.GetType().GetProperty("Variable"); Variable variable = variableProperty.GetValue(expression, null) as Variable; if (variable != null) { expressionString = variable.Name; } } } return expressionString; }
internal static ActivityWithResult TryCreateLiteral(Type type, string expressionText, ParserContext context) { //try easy way first - look if there is a type conversion which supports conversion between expression type and string TypeConverter literalValueConverter = null; bool isQuotedString = false; if (CanTypeBeSerializedAsLiteral(type)) { bool shouldBeQuoted = typeof(string) == type; //whether string begins and ends with quotes '"'. also, if there are //more quotes within than those begining and ending ones, do not bother with literal - assume this is an expression. isQuotedString = shouldBeQuoted && expressionText.StartsWith("\"", StringComparison.CurrentCulture) && expressionText.EndsWith("\"", StringComparison.CurrentCulture) && expressionText.IndexOf("\"", 1, StringComparison.CurrentCulture) == expressionText.Length - 1; //if expression is a string, we must ensure it is quoted, in case of other types - just get the converter if ((shouldBeQuoted && isQuotedString) || !shouldBeQuoted) { literalValueConverter = TypeDescriptor.GetConverter(type); } } //if there is converter - try to convert if (null != literalValueConverter && literalValueConverter.CanConvertFrom(context, typeof(string))) { try { var valueToConvert = isQuotedString ? expressionText.Substring(1, expressionText.Length - 2) : expressionText; var converterValue = literalValueConverter.ConvertFrom(context, CultureInfo.CurrentCulture, valueToConvert); //ok, succeeded - create literal of given type var concreteExpType = typeof(Literal<>).MakeGenericType(type); return (ActivityWithResult)Activator.CreateInstance(concreteExpType, converterValue); } //conversion failed - do nothing, let VB compiler take care of the expression catch { } } return null; }
internal static string GetExpressionString(Activity expression, ModelItem owner) { ParserContext context = new ParserContext(owner); return ExpressionHelper.GetExpressionString(expression, context); }
internal static ActivityWithResult CreateExpressionFromString(Type type, string expressionText, bool isLocation, ParserContext context) { ActivityWithResult newExpression; if (!isLocation) { newExpression = ExpressionHelper.TryCreateLiteral(type, expressionText, context); if (newExpression != null) { return newExpression; } } Type targetExpressionType = null; if (isLocation) { targetExpressionType = typeof(VisualBasicReference<>).MakeGenericType(type); } else { targetExpressionType = typeof(VisualBasicValue<>).MakeGenericType(type); } //create new visual basic value and pass expression text into it newExpression = (ActivityWithResult)Activator.CreateInstance(targetExpressionType, expressionText); //targetExpressionType.GetProperty("Settings").SetValue(newExpression, settings, null); //this code below is never executed - it is placed here only to enable compilation support whenver VisualBasicValue constructor //changes its parameter list. if (null == newExpression) { //if this gives compilation error, please update CreateInstance parameter list above as well! newExpression = new VisualBasicValue<string>(expressionText); } return newExpression; }
//We need to react to OnExpressionChanged, since there might be multiple ExpressionTextBoxes(ETB) associated to a single Expression. //All the ETBs should be updated if the value in any of the ETBs is changed. void OnExpressionChanged() { if (this.HintText == SR.UnsupportedExpressionHintText) { this.HintText = SR.ExpressionDefaultText; this.InitializeHintText(); } if (!this.internalModelItemChange) { if (this.Expression == null) { //new expression is null - there is no text, no previous text, erros should be clear as well as error message this.Text = string.Empty; this.previousText = this.Text; this.ExpressionText = null; this.ValidationState = ValidationState.Valid; } else { this.UpdateValidationState(); object expressionObject = this.Expression.GetCurrentValue(); ActivityWithResult expression = expressionObject as ActivityWithResult; if (VisualBasicEditor.IsSupportedExpressionType(expression)) { String expressionString = null; //create parser context - do not pass ownerActivity - it might be null at this time ParserContext context = new ParserContext(); expressionString = ExpressionHelper.GetExpressionString(expression, context); this.Text = expressionString; this.ExpressionText = expressionString; this.previousText = this.Text; this.IsSupportedExpression = true; } else { this.Text = string.Empty; this.IsSupportedExpression = false; this.HintText = SR.UnsupportedExpressionHintText; } this.isExpressionLoaded = true; if (this.isBeginEditPending) { this.BeginEdit(); } } } internalModelItemChange = false; }