Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / NetFx40 / System.Activities / Microsoft / VisualBasic / Activities / VisualBasicHelper.cs / 1305376 / VisualBasicHelper.cs
//------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
namespace Microsoft.VisualBasic.Activities
{
using System;
using System.Activities;
using System.Activities.ExpressionParser;
using System.CodeDom;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime;
using System.Runtime.Collections;
using System.Text;
using Microsoft.Compiler.VisualBasic;
using System.Collections.ObjectModel;
using Microsoft.VisualBasic.CompilerServices;
class VisualBasicHelper
{
// the following assemblies are provided to the compiler by default
// items are public so the decompiler knows which assemblies it doesn't need to reference for interfaces
public static readonly HashSet DefaultReferencedAssemblies = new HashSet
{
typeof(int).Assembly, // mscorlib
typeof(CodeTypeDeclaration).Assembly, // System
typeof(Expression).Assembly, // System.Core
typeof(Microsoft.VisualBasic.Strings).Assembly, // Microsoft.VisualBasic
typeof(Activity).Assembly // System.Activities
};
// cache for Assembly ==> AssemblyName
// Assembly.GetName() is very very expensive
const int assemblyToAssemblyNameCacheInitSize = 100;
static object assemblyToAssemblyNameCacheLock = new object();
static Hashtable assemblyToAssemblyNameCache;
// this gets the cached AssemblyName
// if not found, it caches the Assembly and creates its AssemblyName set it as the value
// make sure you don't ever call this method for dynamic assemblies that need to be collected
public static AssemblyName GetFastAssemblyName(Assembly assembly)
{
if (assemblyToAssemblyNameCache == null)
{
lock (assemblyToAssemblyNameCacheLock)
{
if (assemblyToAssemblyNameCache == null)
{
assemblyToAssemblyNameCache = new Hashtable(assemblyToAssemblyNameCacheInitSize);
}
}
}
AssemblyName assemblyName = assemblyToAssemblyNameCache[assembly] as AssemblyName;
if (assemblyName != null)
{
return assemblyName;
}
assemblyName = new AssemblyName(assembly.FullName);
lock (assemblyToAssemblyNameCacheLock)
{
assemblyToAssemblyNameCache[assembly] = assemblyName;
}
return assemblyName;
}
// cache for type's all base types, interfaces, generic arguments, element type
// HopperCache is a psuedo-MRU cache
const int typeReferenceCacheMaxSize = 100;
static object typeReferenceCacheLock = new object();
static HopperCache typeReferenceCache = new HopperCache(typeReferenceCacheMaxSize, false);
const int AssemblyCacheInitialSize = 100;
static Hashtable assemblyCache;
static object assemblyCacheLock = new object();
static Assembly GetAssembly(AssemblyName assemblyName)
{
// the following assembly resolution logic
// emulates the Xaml's assembly resolution logic as closely as possible.
// Should Xaml's assembly resolution logic ever change, this code needs update as well.
// please see XamlSchemaContext.ResolveAssembly()
if (assemblyCache == null)
{
lock (assemblyCacheLock)
{
if (assemblyCache == null)
{
assemblyCache = new Hashtable(AssemblyCacheInitialSize, new AssemblyNameEqualityComparer());
}
}
}
Assembly assembly = assemblyCache[assemblyName] as Assembly;
if (assembly != null)
{
return assembly;
}
// search current AppDomain first
// this for-loop part is to ensure that
// loose AssemblyNames get resolved in the same way
// as Xaml would do. that is to find the first match
// found starting from the end of the array of Assemblies
// returned by AppDomain.GetAssemblies()
Assembly[] currentAssemblies = AppDomain.CurrentDomain.GetAssemblies();
for (int i = currentAssemblies.Length - 1; i >= 0; i--)
{
Assembly curAsm = currentAssemblies[i];
if (curAsm.IsDynamic)
{
// ignore dynamic assemblies
continue;
}
AssemblyName curAsmName = GetFastAssemblyName(curAsm);
Version curVersion = curAsmName.Version;
CultureInfo curCulture = curAsmName.CultureInfo;
byte[] curKeyToken = curAsmName.GetPublicKeyToken();
Version reqVersion = assemblyName.Version;
CultureInfo reqCulture = assemblyName.CultureInfo;
byte[] reqKeyToken = assemblyName.GetPublicKeyToken();
if ((String.Compare(curAsmName.Name, assemblyName.Name, StringComparison.OrdinalIgnoreCase) == 0) &&
(reqVersion == null || reqVersion.Equals(curVersion)) &&
(reqCulture == null || reqCulture.Equals(curCulture)) &&
(reqKeyToken == null || AssemblyNameEqualityComparer.IsSameKeyToken(reqKeyToken, curKeyToken)))
{
lock (assemblyCacheLock)
{
assemblyCache[assemblyName] = curAsm;
return curAsm;
}
}
}
assembly = LoadAssembly(assemblyName);
if (assembly != null)
{
lock (assemblyCacheLock)
{
assemblyCache[assemblyName] = assembly;
}
}
return assembly;
}
const int HostedCompilerCacheSize = 10;
static Dictionary, HostedCompiler> HostedCompilerCache;
static HostedCompiler GetCachedHostedCompiler(HashSet assemblySet)
{
if (HostedCompilerCache == null)
{
// HostedCompiler Cache Initializatoin...
IEqualityComparer> AssemblySetEqualityComparer = HashSet.CreateSetComparer();
HostedCompilerCache = new Dictionary, HostedCompiler>(HostedCompilerCacheSize, AssemblySetEqualityComparer);
}
lock (HostedCompilerCache)
{
HostedCompiler hcompiler;
if (HostedCompilerCache.TryGetValue(assemblySet, out hcompiler))
{
return hcompiler;
}
if (HostedCompilerCache.Count >= HostedCompilerCacheSize)
{
// kick one out of the cache
HashSet keyToRemove = HostedCompilerCache.Keys.ElementAtOrDefault>(1);
HostedCompilerCache.Remove(keyToRemove);
}
hcompiler = new HostedCompiler(assemblySet.ToList());
HostedCompilerCache[assemblySet] = hcompiler;
return hcompiler;
}
}
string textToCompile;
HashSet referencedAssemblies;
HashSet namespaceImports;
LocationReferenceEnvironment environment;
CodeActivityMetadata? metadata;
public VisualBasicHelper(string expressionText, HashSet refAssemNames, HashSet namespaceImportsNames)
: this(expressionText)
{
Initialize(refAssemNames, namespaceImportsNames);
}
VisualBasicHelper(string expressionText)
{
this.textToCompile = expressionText;
}
public string TextToCompile { get { return this.textToCompile; } }
void Initialize(HashSet refAssemNames, HashSet namespaceImportsNames)
{
this.namespaceImports = namespaceImportsNames;
foreach (AssemblyName assemblyName in refAssemNames)
{
if (this.referencedAssemblies == null)
{
this.referencedAssemblies = new HashSet();
}
Assembly loaded = GetAssembly(assemblyName);
if (loaded != null)
{
this.referencedAssemblies.Add(loaded);
}
}
}
public static HashSet GetAllImportReferences(Activity root)
{
VisualBasicSettings rootVBSettings = null;
if (root != null)
{
rootVBSettings = VisualBasic.GetSettings(root);
}
// start with our defaults
HashSet localImportReferences = new HashSet(VisualBasicSettings.Default.ImportReferences);
if (rootVBSettings != null)
{
// Xaml file level
localImportReferences.UnionWith(rootVBSettings.ImportReferences);
}
return localImportReferences;
}
public static Expression> Compile(string expressionText, CodeActivityMetadata metadata)
{
HashSet localImportReferences = GetAllImportReferences(metadata.Environment.Root);
VisualBasicHelper helper = new VisualBasicHelper(expressionText);
HashSet localReferenceAssemblies = new HashSet();
HashSet localImports = new HashSet();
foreach (VisualBasicImportReference importReference in localImportReferences)
{
if (importReference.EarlyBoundAssembly != null)
{
// we have an early bound assembly
// this is an indication that we are in the
// context of "compiled Xaml"
// directly add the Assembly to the list
// so that we don't have to go through
// the assembly resolution process
localImports.Add(importReference.Import);
if (helper.referencedAssemblies == null)
{
helper.referencedAssemblies = new HashSet();
}
helper.referencedAssemblies.Add(importReference.EarlyBoundAssembly);
continue;
}
if (importReference.AssemblyName != null)
{
localReferenceAssemblies.Add(importReference.AssemblyName);
}
localImports.Add(importReference.Import);
}
helper.Initialize(localReferenceAssemblies, localImports);
return helper.Compile(metadata);
}
public LambdaExpression CompileNonGeneric(LocationReferenceEnvironment environment)
{
Microsoft.Compiler.VisualBasic.CompilerResults results;
this.environment = environment;
if (this.referencedAssemblies == null)
{
this.referencedAssemblies = new HashSet();
}
this.referencedAssemblies.UnionWith(DefaultReferencedAssemblies);
List importList = new List();
foreach (string namespaceImport in this.namespaceImports)
{
if (!String.IsNullOrEmpty(namespaceImport))
{
importList.Add(new Import(namespaceImport));
}
}
VisualBasicScriptAndTypeScope scriptAndTypeScope = new VisualBasicScriptAndTypeScope(
this.environment,
this.referencedAssemblies.ToList());
IImportScope importScope = new VisualBasicImportScope(importList);
CompilerOptions options = new CompilerOptions();
options.OptionStrict = OptionStrictSetting.On;
CompilerContext context = new CompilerContext(scriptAndTypeScope, scriptAndTypeScope, importScope, options);
HostedCompiler compiler = GetCachedHostedCompiler(this.referencedAssemblies);
lock (compiler)
{
try
{
results = compiler.CompileExpression(this.textToCompile, context);
}
catch (Exception e)
{
if (Fx.IsFatal(e))
{
throw;
}
FxTrace.Exception.TraceUnhandledException(e);
throw;
}
}
if (scriptAndTypeScope.ErrorMessage != null)
{
throw FxTrace.Exception.AsError(new SourceExpressionException(SR.CompilerErrorSpecificExpression(textToCompile, scriptAndTypeScope.ErrorMessage)));
}
if (results.Errors != null && results.Errors.Count > 0)
{
// this expression has problems, so report them
StringBuilder errorString = new StringBuilder();
errorString.AppendLine();
foreach (Error error in results.Errors)
{
errorString.AppendLine(error.Description);
}
throw FxTrace.Exception.AsError(new SourceExpressionException(SR.CompilerErrorSpecificExpression(textToCompile, errorString.ToString())));
}
// replace the field references with variable references to our dummy variables
// and rewrite lambda.body.Type to equal the lambda return type T
LambdaExpression lambda = results.CodeBlock;
if (lambda == null)
{
// ExpressionText was either an empty string or Null
// we return null which eventually evaluates to default(TResult) at execution time.
return null;
}
return Expression.Lambda(lambda.Type, Rewrite(lambda.Body, null), lambda.Parameters);
}
public Expression> Compile(CodeActivityMetadata metadata)
{
this.metadata = metadata;
return Compile(metadata.Environment);
}
// Soft-Link: This method is called through reflection by VisualBasicDesignerHelper.
public Expression> Compile(LocationReferenceEnvironment environment)
{
Microsoft.Compiler.VisualBasic.CompilerResults results;
Type lambdaReturnType = typeof(T);
this.environment = environment;
if (this.referencedAssemblies == null)
{
this.referencedAssemblies = new HashSet();
}
this.referencedAssemblies.UnionWith(DefaultReferencedAssemblies);
List importList = new List();
foreach (string namespaceImport in this.namespaceImports)
{
if (!String.IsNullOrEmpty(namespaceImport))
{
importList.Add(new Import(namespaceImport));
}
}
// ensure the return type's assembly is added to ref assembly list
HashSet allBaseTypes = null;
EnsureTypeReferenced(lambdaReturnType, ref allBaseTypes);
foreach (Type baseType in allBaseTypes)
{
// allBaseTypes list always contains lambdaReturnType
this.referencedAssemblies.Add(baseType.Assembly);
}
VisualBasicScriptAndTypeScope scriptAndTypeScope = new VisualBasicScriptAndTypeScope(
this.environment,
this.referencedAssemblies.ToList());
IImportScope importScope = new VisualBasicImportScope(importList);
CompilerOptions options = new CompilerOptions();
options.OptionStrict = OptionStrictSetting.On;
CompilerContext context = new CompilerContext(scriptAndTypeScope, scriptAndTypeScope, importScope, options);
HostedCompiler compiler = GetCachedHostedCompiler(this.referencedAssemblies);
lock (compiler)
{
try
{
results = compiler.CompileExpression(this.textToCompile, context, lambdaReturnType);
}
catch (Exception e)
{
if (Fx.IsFatal(e))
{
throw;
}
// We never want to end up here, Compiler bugs needs to be fixed.
FxTrace.Exception.TraceUnhandledException(e);
throw;
}
}
if (scriptAndTypeScope.ErrorMessage != null)
{
throw FxTrace.Exception.AsError(new SourceExpressionException(SR.CompilerErrorSpecificExpression(textToCompile, scriptAndTypeScope.ErrorMessage)));
}
if (results.Errors != null && results.Errors.Count > 0)
{
// this expression has problems, so report them
StringBuilder errorString = new StringBuilder();
errorString.AppendLine();
foreach (Error error in results.Errors)
{
errorString.AppendLine(error.Description);
}
throw FxTrace.Exception.AsError(new SourceExpressionException(SR.CompilerErrorSpecificExpression(textToCompile, errorString.ToString())));
}
// replace the field references with variable references to our dummy variables
// and rewrite lambda.body.Type to equal the lambda return type T
LambdaExpression lambda = results.CodeBlock;
if (lambda == null)
{
// ExpressionText was either an empty string or Null
// we return null which eventually evaluates to default(TResult) at execution time.
return null;
}
Expression finalBody = Rewrite(lambda.Body, null);
Fx.Assert(finalBody.Type == lambdaReturnType, "Compiler generated ExpressionTree return type doesn't match the target return type");
// convert it into the our expected lambda format (context => ...)
return Expression.Lambda>(finalBody,
FindParameter(finalBody) ?? ExpressionUtilities.RuntimeContextParameter);
}
#pragma warning disable 618
[SuppressMessage(
"Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods",
MessageId = "System.Reflection.Assembly.LoadWithPartialName",
Justification = "Assembly.LoadWithPartialName is the only method with the right behavior.")]
static Assembly LoadAssembly(AssemblyName assemblyName)
{
Assembly loaded = null;
Fx.Assert(assemblyName.Name != null, "AssemblyName.Name cannot be null");
byte[] publicKeyToken = assemblyName.GetPublicKeyToken();
if (assemblyName.Version != null || assemblyName.CultureInfo != null || publicKeyToken != null)
{
// Assembly.Load(string)
try
{
loaded = Assembly.Load(assemblyName.FullName);
}
catch (Exception ex)
{
if (ex is FileNotFoundException ||
ex is FileLoadException ||
(ex is TargetInvocationException &&
(((TargetInvocationException)ex).InnerException is FileNotFoundException ||
((TargetInvocationException)ex).InnerException is FileNotFoundException)))
{
loaded = null;
FxTrace.Exception.AsWarning(ex);
}
else
{
throw;
}
}
}
else
{
// partial assembly name
loaded = Assembly.LoadWithPartialName(assemblyName.FullName);
}
return loaded;
}
#pragma warning restore 618
Expression Rewrite(Expression expression, ReadOnlyCollection lambdaParameters)
{
if (expression == null)
{
return null;
}
switch (expression.NodeType)
{
case ExpressionType.Add:
case ExpressionType.AddChecked:
case ExpressionType.And:
case ExpressionType.AndAlso:
case ExpressionType.Coalesce:
case ExpressionType.Divide:
case ExpressionType.Equal:
case ExpressionType.ExclusiveOr:
case ExpressionType.GreaterThan:
case ExpressionType.GreaterThanOrEqual:
case ExpressionType.LeftShift:
case ExpressionType.LessThan:
case ExpressionType.LessThanOrEqual:
case ExpressionType.Modulo:
case ExpressionType.Multiply:
case ExpressionType.MultiplyChecked:
case ExpressionType.NotEqual:
case ExpressionType.Or:
case ExpressionType.OrElse:
case ExpressionType.Power:
case ExpressionType.RightShift:
case ExpressionType.Subtract:
case ExpressionType.SubtractChecked:
BinaryExpression binaryExpression = (BinaryExpression)expression;
return Expression.MakeBinary(
binaryExpression.NodeType,
Rewrite(binaryExpression.Left, lambdaParameters),
Rewrite(binaryExpression.Right, lambdaParameters),
binaryExpression.IsLiftedToNull,
binaryExpression.Method,
(LambdaExpression)Rewrite(binaryExpression.Conversion, lambdaParameters));
case ExpressionType.Conditional:
ConditionalExpression conditional = (ConditionalExpression)expression;
return Expression.Condition(
Rewrite(conditional.Test, lambdaParameters),
Rewrite(conditional.IfTrue, lambdaParameters),
Rewrite(conditional.IfFalse, lambdaParameters));
case ExpressionType.Constant:
return expression;
case ExpressionType.Invoke:
InvocationExpression invocation = (InvocationExpression)expression;
return Expression.Invoke(
Rewrite(invocation.Expression, lambdaParameters),
from a in invocation.Arguments select Rewrite(a, lambdaParameters));
case ExpressionType.Lambda:
LambdaExpression lambda = (LambdaExpression)expression;
return Expression.Lambda(
lambda.Type,
Rewrite(lambda.Body, lambda.Parameters),
lambda.Parameters);
case ExpressionType.ListInit:
ListInitExpression listInit = (ListInitExpression)expression;
return Expression.ListInit(
(NewExpression)Rewrite(listInit.NewExpression, lambdaParameters),
from ei in listInit.Initializers
select Expression.ElementInit(
ei.AddMethod,
from arg in ei.Arguments select Rewrite(arg, lambdaParameters)));
case ExpressionType.Parameter:
ParameterExpression variableExpression = (ParameterExpression)expression;
{
if (lambdaParameters != null && lambdaParameters.Contains(variableExpression))
{
return variableExpression;
}
string name = variableExpression.Name;
LocationReferenceEnvironment currentEnvironment = this.environment;
while (currentEnvironment != null)
{
foreach (LocationReference reference in currentEnvironment.GetLocationReferences())
{
if (string.Equals(reference.Name, name, StringComparison.OrdinalIgnoreCase))
{
LocationReference finalReference = reference;
if (this.metadata != null)
{
CodeActivityMetadata localMetadata = this.metadata.Value;
LocationReference inlinedReference;
if (localMetadata.TryGetInlinedLocationReference(reference, out inlinedReference))
{
finalReference = inlinedReference;
}
}
return ExpressionUtilities.CreateIdentifierExpression(finalReference);
}
}
currentEnvironment = currentEnvironment.Parent;
}
// if we are here, this variableExpression is a temp variable
// generated by the compiler.
return variableExpression;
}
case ExpressionType.MemberAccess:
MemberExpression memberExpression = (MemberExpression)expression;
return Expression.MakeMemberAccess(
Rewrite(memberExpression.Expression, lambdaParameters),
memberExpression.Member);
case ExpressionType.MemberInit:
MemberInitExpression memberInit = (MemberInitExpression)expression;
return Expression.MemberInit(
(NewExpression)Rewrite(memberInit.NewExpression, lambdaParameters),
from b in memberInit.Bindings select Rewrite(b, lambdaParameters));
case ExpressionType.ArrayIndex:
// ArrayIndex can be a MethodCallExpression or a BinaryExpression
MethodCallExpression arrayIndex = expression as MethodCallExpression;
if (arrayIndex != null)
{
return Expression.ArrayIndex(
Rewrite(arrayIndex.Object, lambdaParameters),
from a in arrayIndex.Arguments select Rewrite(a, lambdaParameters));
}
BinaryExpression alternateIndex = (BinaryExpression)expression;
return Expression.ArrayIndex(
Rewrite(alternateIndex.Left, lambdaParameters),
Rewrite(alternateIndex.Right, lambdaParameters));
case ExpressionType.Call:
MethodCallExpression methodCall = (MethodCallExpression)expression;
return Expression.Call(
Rewrite(methodCall.Object, lambdaParameters),
methodCall.Method,
from a in methodCall.Arguments select Rewrite(a, lambdaParameters));
case ExpressionType.NewArrayInit:
NewArrayExpression newArray = (NewArrayExpression)expression;
return Expression.NewArrayInit(
newArray.Type.GetElementType(),
from e in newArray.Expressions select Rewrite(e, lambdaParameters));
case ExpressionType.NewArrayBounds:
NewArrayExpression newArrayBounds = (NewArrayExpression)expression;
return Expression.NewArrayBounds(
newArrayBounds.Type.GetElementType(),
from e in newArrayBounds.Expressions select Rewrite(e, lambdaParameters));
case ExpressionType.New:
NewExpression newExpression = (NewExpression)expression;
if (newExpression.Constructor == null)
{
// must be creating a valuetype
Fx.Assert(newExpression.Arguments.Count == 0, "NewExpression with null Constructor but some arguments");
return expression;
}
return Expression.New(
newExpression.Constructor,
from a in newExpression.Arguments select Rewrite(a, lambdaParameters));
case ExpressionType.TypeIs:
TypeBinaryExpression typeBinary = (TypeBinaryExpression)expression;
return Expression.TypeIs(
Rewrite(typeBinary.Expression, lambdaParameters),
typeBinary.TypeOperand);
case ExpressionType.ArrayLength:
case ExpressionType.Convert:
case ExpressionType.ConvertChecked:
case ExpressionType.Negate:
case ExpressionType.NegateChecked:
case ExpressionType.Not:
case ExpressionType.Quote:
case ExpressionType.TypeAs:
UnaryExpression unary = (UnaryExpression)expression;
return Expression.MakeUnary(
unary.NodeType,
Rewrite(unary.Operand, lambdaParameters),
unary.Type,
unary.Method);
case ExpressionType.UnaryPlus:
UnaryExpression unaryPlus = (UnaryExpression)expression;
return Expression.UnaryPlus(
Rewrite(unaryPlus.Operand, lambdaParameters),
unaryPlus.Method);
// Expression Tree V2.0 types. This is due to the hosted VB compiler generating ET V2.0 nodes
case ExpressionType.Block:
BlockExpression block = (BlockExpression)expression;
List parameterList = new List();
foreach (ParameterExpression e in block.Variables)
{
parameterList.Add((ParameterExpression)Rewrite(e, lambdaParameters));
}
List expressionList = new List();
foreach (Expression e in block.Expressions)
{
expressionList.Add(Rewrite(e, lambdaParameters));
}
return Expression.Block(parameterList, expressionList);
case ExpressionType.Assign:
BinaryExpression assign = (BinaryExpression)expression;
return Expression.Assign(Rewrite(assign.Left, lambdaParameters), Rewrite(assign.Right, lambdaParameters));
}
Fx.Assert("Don't understand expression type " + expression.NodeType);
return expression;
}
MemberBinding Rewrite(MemberBinding binding, ReadOnlyCollection lambdaParameters)
{
switch (binding.BindingType)
{
case MemberBindingType.Assignment:
MemberAssignment assignment = (MemberAssignment)binding;
return Expression.Bind(assignment.Member, Rewrite(assignment.Expression, lambdaParameters));
case MemberBindingType.ListBinding:
MemberListBinding list = (MemberListBinding)binding;
return Expression.ListBind(
list.Member,
from li in list.Initializers
select
Expression.ElementInit(
li.AddMethod,
from arg in li.Arguments select Rewrite(arg, lambdaParameters)));
case MemberBindingType.MemberBinding:
MemberMemberBinding member = (MemberMemberBinding)binding;
return Expression.MemberBind(
member.Member,
from b in member.Bindings select Rewrite(b, lambdaParameters));
default:
Fx.Assert("MemberBinding type '" + binding.BindingType + "' is not supported.");
return binding;
}
}
static ParameterExpression FindParameter(Expression expression)
{
if (expression == null)
{
return null;
}
switch (expression.NodeType)
{
case ExpressionType.Add:
case ExpressionType.AddChecked:
case ExpressionType.And:
case ExpressionType.AndAlso:
case ExpressionType.Coalesce:
case ExpressionType.Divide:
case ExpressionType.Equal:
case ExpressionType.ExclusiveOr:
case ExpressionType.GreaterThan:
case ExpressionType.GreaterThanOrEqual:
case ExpressionType.LeftShift:
case ExpressionType.LessThan:
case ExpressionType.LessThanOrEqual:
case ExpressionType.Modulo:
case ExpressionType.Multiply:
case ExpressionType.MultiplyChecked:
case ExpressionType.NotEqual:
case ExpressionType.Or:
case ExpressionType.OrElse:
case ExpressionType.Power:
case ExpressionType.RightShift:
case ExpressionType.Subtract:
case ExpressionType.SubtractChecked:
BinaryExpression binaryExpression = (BinaryExpression)expression;
return FindParameter(binaryExpression.Left) ?? FindParameter(binaryExpression.Right);
case ExpressionType.Conditional:
ConditionalExpression conditional = (ConditionalExpression)expression;
return FindParameter(conditional.Test) ?? FindParameter(conditional.IfTrue) ?? FindParameter(conditional.IfFalse);
case ExpressionType.Constant:
return null;
case ExpressionType.Invoke:
InvocationExpression invocation = (InvocationExpression)expression;
return FindParameter(invocation.Expression) ?? FindParameter(invocation.Arguments);
case ExpressionType.Lambda:
LambdaExpression lambda = (LambdaExpression)expression;
return FindParameter(lambda.Body);
case ExpressionType.ListInit:
ListInitExpression listInit = (ListInitExpression)expression;
return FindParameter(listInit.NewExpression) ?? FindParameter(listInit.Initializers);
case ExpressionType.MemberAccess:
MemberExpression memberExpression = (MemberExpression)expression;
return FindParameter(memberExpression.Expression);
case ExpressionType.MemberInit:
MemberInitExpression memberInit = (MemberInitExpression)expression;
return FindParameter(memberInit.NewExpression) ?? FindParameter(memberInit.Bindings);
case ExpressionType.ArrayIndex:
// ArrayIndex can be a MethodCallExpression or a BinaryExpression
MethodCallExpression arrayIndex = expression as MethodCallExpression;
if (arrayIndex != null)
{
return FindParameter(arrayIndex.Object) ?? FindParameter(arrayIndex.Arguments);
}
BinaryExpression alternateIndex = (BinaryExpression)expression;
return FindParameter(alternateIndex.Left) ?? FindParameter(alternateIndex.Right);
case ExpressionType.Call:
MethodCallExpression methodCall = (MethodCallExpression)expression;
return FindParameter(methodCall.Object) ?? FindParameter(methodCall.Arguments);
case ExpressionType.NewArrayInit:
case ExpressionType.NewArrayBounds:
NewArrayExpression newArray = (NewArrayExpression)expression;
return FindParameter(newArray.Expressions);
case ExpressionType.New:
NewExpression newExpression = (NewExpression)expression;
return FindParameter(newExpression.Arguments);
case ExpressionType.Parameter:
ParameterExpression parameterExpression = (ParameterExpression)expression;
if (parameterExpression.Type == typeof(ActivityContext) && parameterExpression.Name == "context")
{
return parameterExpression;
}
return null;
case ExpressionType.TypeIs:
TypeBinaryExpression typeBinary = (TypeBinaryExpression)expression;
return FindParameter(typeBinary.Expression);
case ExpressionType.ArrayLength:
case ExpressionType.Convert:
case ExpressionType.ConvertChecked:
case ExpressionType.Negate:
case ExpressionType.NegateChecked:
case ExpressionType.Not:
case ExpressionType.Quote:
case ExpressionType.TypeAs:
case ExpressionType.UnaryPlus:
UnaryExpression unary = (UnaryExpression)expression;
return FindParameter(unary.Operand);
// Expression Tree V2.0 types
case ExpressionType.Block:
BlockExpression block = (BlockExpression)expression;
ParameterExpression toReturn = FindParameter(block.Expressions);
if (toReturn != null)
{
return toReturn;
}
List variableList = new List();
foreach (ParameterExpression variable in block.Variables)
{
variableList.Add(variable);
}
return FindParameter(variableList);
case ExpressionType.Assign:
BinaryExpression assign = (BinaryExpression)expression;
return FindParameter(assign.Left) ?? FindParameter(assign.Right);
}
Fx.Assert("Don't understand expression type " + expression.NodeType);
return null;
}
static ParameterExpression FindParameter(ICollection collection)
{
foreach (Expression expression in collection)
{
ParameterExpression result = FindParameter(expression);
if (result != null)
{
return result;
}
}
return null;
}
static ParameterExpression FindParameter(ICollection collection)
{
foreach (ElementInit init in collection)
{
ParameterExpression result = FindParameter(init.Arguments);
if (result != null)
{
return result;
}
}
return null;
}
static ParameterExpression FindParameter(ICollection bindings)
{
foreach (MemberBinding binding in bindings)
{
ParameterExpression result;
switch (binding.BindingType)
{
case MemberBindingType.Assignment:
MemberAssignment assignment = (MemberAssignment)binding;
result = FindParameter(assignment.Expression);
break;
case MemberBindingType.ListBinding:
MemberListBinding list = (MemberListBinding)binding;
result = FindParameter(list.Initializers);
break;
case MemberBindingType.MemberBinding:
MemberMemberBinding member = (MemberMemberBinding)binding;
result = FindParameter(member.Bindings);
break;
default:
Fx.Assert("MemberBinding type '" + binding.BindingType + "' is not supported.");
result = null;
break;
}
if (result != null)
{
return result;
}
}
return null;
}
static void EnsureTypeReferenced(Type type, ref HashSet typeReferences)
{
// lookup cache
// underlying assumption is that type's inheritance(or interface) hierarchy
// stays static throughout the lifetime of AppDomain
HashSet alreadyVisited = (HashSet)typeReferenceCache.GetValue(typeReferenceCacheLock, type);
if (alreadyVisited != null)
{
if (typeReferences == null)
{
// used in VBHelper.Compile<>
// must not alter this set being returned for integrity of cache
typeReferences = alreadyVisited;
}
else
{
// used in VBDesignerHelper.FindTypeReferences
typeReferences.UnionWith(alreadyVisited);
}
return;
}
alreadyVisited = new HashSet();
EnsureTypeReferencedRecurse(type, alreadyVisited);
// cache resulting alreadyVisited set for fast future lookup
lock (typeReferenceCacheLock)
{
typeReferenceCache.Add(type, alreadyVisited);
}
if (typeReferences == null)
{
// used in VBHelper.Compile<>
// must not alter this set being returned for integrity of cache
typeReferences = alreadyVisited;
}
else
{
// used in VBDesignerHelper.FindTypeReferences
typeReferences.UnionWith(alreadyVisited);
}
return;
}
static void EnsureTypeReferencedRecurse(Type type, HashSet alreadyVisited)
{
if (alreadyVisited.Contains(type))
{
// this prevents circular reference
// example), class Foo : IBar
return;
}
alreadyVisited.Add(type);
// make sure any interfaces needed by this type are referenced
Type[] interfaces = type.GetInterfaces();
for (int i = 0; i < interfaces.Length; ++i)
{
EnsureTypeReferencedRecurse(interfaces[i], alreadyVisited);
}
// same for base types
Type baseType = type.BaseType;
while ((baseType != null) && (baseType != TypeHelper.ObjectType))
{
EnsureTypeReferencedRecurse(baseType, alreadyVisited);
baseType = baseType.BaseType;
}
// for generic types, all type arguments
if (type.IsGenericType)
{
Type[] typeArgs = type.GetGenericArguments();
for (int i = 1; i < typeArgs.Length; ++i)
{
EnsureTypeReferencedRecurse(typeArgs[i], alreadyVisited);
}
}
// array types
if (type.HasElementType)
{
EnsureTypeReferencedRecurse(type.GetElementType(), alreadyVisited);
}
return;
}
class VisualBasicImportScope : IImportScope
{
IList importList;
public VisualBasicImportScope(IList importList)
{
this.importList = importList;
}
public IList GetImports()
{
return this.importList;
}
}
class VisualBasicScriptAndTypeScope : IScriptScope, ITypeScope
{
LocationReferenceEnvironment environmentProvider;
List assemblies;
string errorMessage;
public VisualBasicScriptAndTypeScope(LocationReferenceEnvironment environmentProvider, List assemblies)
{
this.environmentProvider = environmentProvider;
this.assemblies = assemblies;
}
public string ErrorMessage
{
get { return this.errorMessage; }
}
public Type FindVariable(string name)
{
LocationReference referenceToReturn = null;
bool isFirstMatchAlreadyFound = false;
bool isSecondMatchFound = false;
LocationReferenceEnvironment currentEnvironment = this.environmentProvider;
while (currentEnvironment != null && !isSecondMatchFound)
{
foreach (LocationReference reference in currentEnvironment.GetLocationReferences())
{
if (string.Equals(reference.Name, name, StringComparison.OrdinalIgnoreCase))
{
if (isFirstMatchAlreadyFound)
{
isSecondMatchFound = true;
break;
}
isFirstMatchAlreadyFound = true;
referenceToReturn = reference;
}
}
currentEnvironment = currentEnvironment.Parent;
}
if (isSecondMatchFound)
{
// we have duplicate variable names across all visible environments!!!!
// compile error here!!!!
this.errorMessage = SR.AmbiguousVBVariableReference(name);
return null;
}
if (isFirstMatchAlreadyFound)
{
Type referenceType = referenceToReturn.Type;
HashSet allBaseTypes = null;
VisualBasicHelper.EnsureTypeReferenced(referenceType, ref allBaseTypes);
foreach (Type baseType in allBaseTypes)
{
// allBaseTypes always contains referenceType
if (!this.assemblies.Contains(baseType.Assembly))
{
// if this.assemblies list doesn't contain all the assemblies
// that define referenceType and its all base types,
// then we gracefully fail compilation by pretending
// the identifier is unknown. Otherwise the VB compiler may crash
return null;
}
}
return referenceType;
}
return null;
}
public Type[] FindTypes(string typeName, string nsPrefix)
{
return null;
}
public bool NamespaceExists(string ns)
{
return false;
}
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- NameValueCollection.cs
- SerTrace.cs
- ApplicationFileParser.cs
- File.cs
- CodeArrayIndexerExpression.cs
- RootDesignerSerializerAttribute.cs
- SimpleModelProvider.cs
- HttpHostedTransportConfiguration.cs
- InstanceOwnerQueryResult.cs
- Operator.cs
- ValuePatternIdentifiers.cs
- MgmtConfigurationRecord.cs
- SqlNamer.cs
- ExecutedRoutedEventArgs.cs
- ScriptingJsonSerializationSection.cs
- ContextMenu.cs
- ColorMatrix.cs
- AuthenticationConfig.cs
- ConfigXmlAttribute.cs
- EntityAdapter.cs
- XslAst.cs
- WebPermission.cs
- log.cs
- BlurEffect.cs
- InputProcessorProfilesLoader.cs
- SystemFonts.cs
- XmlObjectSerializerReadContext.cs
- BindingMemberInfo.cs
- PerfService.cs
- ToolBar.cs
- RuntimeIdentifierPropertyAttribute.cs
- Size3D.cs
- CodeGeneratorOptions.cs
- ExpressionNormalizer.cs
- SQLInt16.cs
- AppModelKnownContentFactory.cs
- System.Data_BID.cs
- TableStyle.cs
- EventRecordWrittenEventArgs.cs
- DefaultHttpHandler.cs
- GeneralTransform3DGroup.cs
- CompositeControl.cs
- IndicFontClient.cs
- WebEventTraceProvider.cs
- SQLInt32.cs
- FixedTextBuilder.cs
- SiteMapNode.cs
- CheckBoxField.cs
- RangeValidator.cs
- ExtenderHelpers.cs
- StyleConverter.cs
- JavaScriptString.cs
- HtmlInputButton.cs
- PeerResolver.cs
- XamlReaderConstants.cs
- ExpressionWriter.cs
- AdditionalEntityFunctions.cs
- XmlHierarchyData.cs
- ErrorTolerantObjectWriter.cs
- StreamBodyWriter.cs
- ObjectIDGenerator.cs
- Int32AnimationBase.cs
- MasterPageCodeDomTreeGenerator.cs
- ContextProperty.cs
- ObjectView.cs
- UnauthorizedWebPart.cs
- DeploymentSection.cs
- DefaultAuthorizationContext.cs
- SchemaManager.cs
- TextMarkerSource.cs
- xmlsaver.cs
- ScriptingAuthenticationServiceSection.cs
- ColorTransform.cs
- XmlLinkedNode.cs
- SqlDataSourceStatusEventArgs.cs
- CqlBlock.cs
- NTAccount.cs
- WorkflowWebService.cs
- Version.cs
- MetadataException.cs
- NativeActivity.cs
- ECDiffieHellmanCng.cs
- SchemaMapping.cs
- HttpMethodConstraint.cs
- SmiContext.cs
- ComponentConverter.cs
- XmlSerializerSection.cs
- Utilities.cs
- CaseStatementSlot.cs
- HttpDebugHandler.cs
- OdbcParameterCollection.cs
- TableColumn.cs
- SettingsBindableAttribute.cs
- DynamicUpdateCommand.cs
- StringUtil.cs
- SubpageParaClient.cs
- CompilationUnit.cs
- SequenceDesigner.cs
- XmlIgnoreAttribute.cs
- RequiredFieldValidator.cs