bool DoValidation(ExpressionValidationContext validationContext, out string errorMessage) { Fx.Assert(validationContext != null, "only work when context is not null"); errorMessage = null; //validate //if the text is empty we clear the error message if (string.IsNullOrEmpty(validationContext.ExpressionText)) { errorMessage = null; return true; } // if the expression text is different from the last time we run the validation we run the validation else if (!string.Equals(validationContext.ExpressionText, validationContext.ValidatedExpressionText)) { Type expReturnType = null; string newExpressionText = null; SourceExpressionException compileErrorMessages = null; VisualBasicSettings settings = null; try { CreateVBExpression(validationContext, out newExpressionText, out expReturnType, out compileErrorMessages, out settings); if (compileErrorMessages != null) { errorMessage = compileErrorMessages.Message; } } catch (Exception err) { errorMessage = err.Message; } return true; } return false; }
private Activity CreateVBExpression() { Activity valueExpression = null; if (this.OwnerActivity != null) { ExpressionValidationContext validationContext = new ExpressionValidationContext(this); Type expReturnType = null; string newExpressionText = null; SourceExpressionException compileErrorMessages; try { VisualBasicSettings settings = null; valueExpression = CreateVBExpression(validationContext, out newExpressionText, out expReturnType, out compileErrorMessages, out settings); if (settings != null) { Fx.Assert(this.Context != null, "editing context cannot be null"); //merge with import designer foreach (VisualBasicImportReference reference in settings.ImportReferences) { ImportDesigner.AddImport(reference.Import, this.Context); } } if (!string.IsNullOrEmpty(newExpressionText)) { this.previousText = this.Text; this.Text = newExpressionText; } } catch (Exception err) { //if the VisualBasicDesignerHelper were able to resolve the type we use that if (expReturnType == null) { //if not we try to use the expression type expReturnType = this.ExpressionType; } //if expression type is also null, the we use object if (expReturnType == null) { expReturnType = typeof(object); } valueExpression = VisualBasicEditor.CreateExpressionFromString(expReturnType, this.Text, UseLocationExpression, validationContext.ParserContext); Trace.WriteLine(string.Format(CultureInfo.CurrentUICulture, "{0}\r\n{1}", err.Message, err.StackTrace)); } this.ExpressionText = this.Text; } else { // If the OwnerActivity is null, do not try to compile the expression otherwise VS will crash // Inform the user that OwnerActivity is null (i.e. there is a error in their code) Trace.WriteLine("ExpressionTextBox OwnerActivity is null."); } return valueExpression; }
private static Activity CreateVBExpression(ExpressionValidationContext context, out string newExpressionText, out Type expReturnType, out SourceExpressionException compileErrorMessages, out VisualBasicSettings vbSettings) { expReturnType = null; newExpressionText = null; compileErrorMessages = null; vbSettings = null; //try easy way first - look if there is a type converter which supports conversion between expression type and string ActivityWithResult literal = null; try { if (!context.UseLocationExpression) { literal = ExpressionHelper.TryCreateLiteral(context.ExpressionType, context.ExpressionText, context.ParserContext); } if (literal != null) { //need to get new expression text - converter might have changed its format, and we want it to be up to date IValueSerializableExpression serializableExpression = literal as IValueSerializableExpression; Fx.Assert(serializableExpression != null, "the expression has to be a Literal<>, which should be IValueSerializableExpression"); if (serializableExpression.CanConvertToString(context.ParserContext)) { bool shouldBeQuoted = typeof(string) == context.ExpressionType || typeof(Uri) == context.ExpressionType; //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. bool isQuotedString = shouldBeQuoted && context.ExpressionText.StartsWith("\"", StringComparison.CurrentCulture) && context.ExpressionText.EndsWith("\"", StringComparison.CurrentCulture) && context.ExpressionText.IndexOf("\"", 1, StringComparison.CurrentCulture) == context.ExpressionText.Length - 1; var formatString = isQuotedString ? "\"{0}\"" : "{0}"; newExpressionText = string.Format(CultureInfo.InvariantCulture, formatString, serializableExpression.ConvertToString(context.ParserContext)); } } } //conversion failed - do nothing, let VB compiler take care of the expression catch { } Activity valueExpression = literal; if (null == valueExpression) { if (!context.UseLocationExpression) { //Compile for validation. valueExpression = VisualBasicDesignerHelper.CreatePrecompiledVisualBasicValue(context.ExpressionType, context.ExpressionText, context.ParserContext.Namespaces, context.ReferencedAssemblies, context.ParserContext, out expReturnType, out compileErrorMessages, out vbSettings); } else { //Compile for validation. valueExpression = VisualBasicDesignerHelper.CreatePrecompiledVisualBasicReference(context.ExpressionType, context.ExpressionText, context.ParserContext.Namespaces, context.ReferencedAssemblies, context.ParserContext, out expReturnType, out compileErrorMessages, out vbSettings); } ////It's possible the inferred type of expression is a dynamic type (e.g. delegate type), in this case it will cause serialization failure. ////To prevent this, we'll always convert the expression type to be object if the inferred type is in dynamic assembly and user doesn't specify any ExpressionType property if ((expReturnType.Assembly.IsDynamic) && (context.ExpressionType == null)) { ActivityWithResult originalExpression = valueExpression as ActivityWithResult; ActivityWithResult morphedExpression; if (ExpressionHelper.TryMorphExpression(originalExpression, ExpressionHelper.IsGenericLocationExpressionType(originalExpression), typeof(object), context.EditingContext, out morphedExpression)) { valueExpression = morphedExpression; } } } return valueExpression; }