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 HashSetDefaultReferencedAssemblies = 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
- SizeAnimationClockResource.cs
- SqlFacetAttribute.cs
- XmlDataDocument.cs
- HyperLinkField.cs
- Rect3DValueSerializer.cs
- SoapDocumentServiceAttribute.cs
- CollectionViewGroupRoot.cs
- ServiceDescriptions.cs
- xamlnodes.cs
- PrePostDescendentsWalker.cs
- CngAlgorithm.cs
- WebScriptMetadataMessage.cs
- DiagnosticEventProvider.cs
- HtmlWindowCollection.cs
- ListViewGroup.cs
- ExpressionContext.cs
- TemplateLookupAction.cs
- LogWriteRestartAreaState.cs
- SqlDataSourceQueryEditorForm.cs
- SetIndexBinder.cs
- DomainConstraint.cs
- GridViewRow.cs
- DbMetaDataFactory.cs
- Keywords.cs
- TailCallAnalyzer.cs
- MediaCommands.cs
- CommonObjectSecurity.cs
- RoutedCommand.cs
- TimelineGroup.cs
- ScopelessEnumAttribute.cs
- ProgressBarRenderer.cs
- ForwardPositionQuery.cs
- IsolationInterop.cs
- Stylesheet.cs
- InputProviderSite.cs
- IndentedWriter.cs
- DesignerVerb.cs
- SrgsSubset.cs
- CalendarSelectionChangedEventArgs.cs
- TreePrinter.cs
- AutoGeneratedFieldProperties.cs
- GridEntryCollection.cs
- ServiceNameElement.cs
- TextRunCache.cs
- FontStretches.cs
- WindowsListViewGroup.cs
- WebServiceClientProxyGenerator.cs
- ConfigurationCollectionAttribute.cs
- InArgumentConverter.cs
- TextBoxLine.cs
- InteropAutomationProvider.cs
- XmlAttributeHolder.cs
- WeakReferenceEnumerator.cs
- ElementMarkupObject.cs
- HwndProxyElementProvider.cs
- DesignerView.Commands.cs
- ClientProxyGenerator.cs
- HitTestParameters3D.cs
- DateTime.cs
- ReversePositionQuery.cs
- figurelengthconverter.cs
- InternalDuplexChannelFactory.cs
- sqlmetadatafactory.cs
- HttpModuleAction.cs
- querybuilder.cs
- JsonObjectDataContract.cs
- lengthconverter.cs
- EventProvider.cs
- PrintPageEvent.cs
- DataGridItemCollection.cs
- HttpContext.cs
- BinaryFormatterWriter.cs
- ModelPropertyCollectionImpl.cs
- MetadataItemEmitter.cs
- ETagAttribute.cs
- BamlLocalizer.cs
- MeasureData.cs
- FixedFindEngine.cs
- AnalyzedTree.cs
- TransformerInfoCollection.cs
- BatchStream.cs
- httpserverutility.cs
- XmlQueryStaticData.cs
- NotificationContext.cs
- SamlAuthenticationStatement.cs
- COM2TypeInfoProcessor.cs
- VisualBrush.cs
- CompositeKey.cs
- TemplateDefinition.cs
- PageHandlerFactory.cs
- Geometry.cs
- InputProcessorProfiles.cs
- InternalsVisibleToAttribute.cs
- ExtractCollection.cs
- ResXResourceReader.cs
- CacheAxisQuery.cs
- Formatter.cs
- BitmapEffectDrawingContextState.cs
- Pool.cs
- DropSource.cs