|
//-----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
namespace Microsoft.VisualBasic.Activities
{
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Activities;
using System.Activities.Expressions;
using System.Activities.ExpressionParser;
using System.Activities.XamlIntegration;
using System.Linq.Expressions;
using System.Windows.Markup;
using System.ComponentModel;
using System.Runtime;
[DebuggerStepThrough]
public sealed class VisualBasicReference<TResult> : CodeActivity<Location<TResult>>, IValueSerializableExpression, IExpressionContainer, ITextExpression
{
Expression<Func<ActivityContext, TResult>> expressionTree;
LocationFactory<TResult> locationFactory;
CompiledExpressionInvoker invoker;
public VisualBasicReference()
: base()
{
this.UseOldFastPath = true;
}
public VisualBasicReference(string expressionText)
: this()
{
this.ExpressionText = expressionText;
}
public string ExpressionText
{
get;
set;
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public string Language
{
get
{
return VisualBasicHelper.Language;
}
}
public bool RequiresCompilation
{
get
{
return false;
}
}
protected override Location<TResult> Execute(CodeActivityContext context)
{
if (!this.invoker.IsStaticallyCompiled)
{
if (this.expressionTree != null)
{
if (this.locationFactory == null)
{
this.locationFactory = ExpressionUtilities.CreateLocationFactory<TResult>(this.expressionTree);
}
return this.locationFactory.CreateLocation(context);
}
else
{
return null;
}
}
else
{
return (Location<TResult>) this.invoker.InvokeExpression(context);
}
}
protected override void CacheMetadata(CodeActivityMetadata metadata)
{
this.expressionTree = null;
this.invoker = new CompiledExpressionInvoker(this, true, metadata);
if (this.invoker.IsStaticallyCompiled)
{
return;
}
string validationError;
// If ICER is not implemented that means we haven't been compiled
CodeActivityPublicEnvironmentAccessor publicAccessor = CodeActivityPublicEnvironmentAccessor.Create(metadata);
this.expressionTree = this.CompileLocationExpression(publicAccessor, out validationError);
if (validationError != null)
{
metadata.AddValidationError(validationError);
}
}
public bool CanConvertToString(IValueSerializerContext context)
{
// we can always convert to a string
return true;
}
public string ConvertToString(IValueSerializerContext context)
{
// Return our bracket-escaped text
return "[" + this.ExpressionText + "]";
}
public Expression GetExpressionTree()
{
if (this.IsMetadataCached)
{
if (this.expressionTree == null)
{
string validationError;
// it's safe to create this CodeActivityMetadata here,
// because we know we are using it only as lookup purpose.
CodeActivityMetadata metadata = new CodeActivityMetadata(this, this.GetParentEnvironment(), false);
CodeActivityPublicEnvironmentAccessor publicAccessor = CodeActivityPublicEnvironmentAccessor.CreateWithoutArgument(metadata);
try
{
this.expressionTree = this.CompileLocationExpression(publicAccessor, out validationError);
if (validationError != null)
{
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.VBExpressionTamperedSinceLastCompiled(validationError)));
}
}
finally
{
metadata.Dispose();
}
}
Fx.Assert(this.expressionTree.NodeType == ExpressionType.Lambda, "Lambda expression required");
return ExpressionUtilities.RewriteNonCompiledExpressionTree((LambdaExpression)this.expressionTree);
}
else
{
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.ActivityIsUncached));
}
}
private Expression<Func<ActivityContext, TResult>> CompileLocationExpression(CodeActivityPublicEnvironmentAccessor publicAccessor, out string validationError)
{
Expression<Func<ActivityContext, TResult>> expressionTreeToReturn = null;
validationError = null;
try
{
expressionTreeToReturn = VisualBasicHelper.Compile<TResult>(this.ExpressionText, publicAccessor, true);
// inspect the expressionTree to see if it is a valid location expression(L-value)
string extraErrorMessage = null;
if (!publicAccessor.ActivityMetadata.HasViolations && (expressionTreeToReturn == null || !ExpressionUtilities.IsLocation(expressionTreeToReturn, typeof(TResult), out extraErrorMessage)))
{
string errorMessage = SR.InvalidLValueExpression;
if (extraErrorMessage != null)
{
errorMessage += ":" + extraErrorMessage;
}
expressionTreeToReturn = null;
validationError = SR.CompilerErrorSpecificExpression(this.ExpressionText, errorMessage);
}
}
catch (SourceExpressionException e)
{
validationError = e.Message;
}
return expressionTreeToReturn;
}
}
}
|