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
- TemplateContainer.cs
- RoleBoolean.cs
- ECDiffieHellman.cs
- FastEncoderWindow.cs
- OdbcParameter.cs
- BulletedList.cs
- DependencyPropertyAttribute.cs
- NavigationProperty.cs
- StringFunctions.cs
- DefaultWorkflowSchedulerService.cs
- Pair.cs
- EdmComplexPropertyAttribute.cs
- SmtpNetworkElement.cs
- BuildManager.cs
- PreservationFileReader.cs
- DXD.cs
- ReflectionTypeLoadException.cs
- DataSourceProvider.cs
- CodeAccessSecurityEngine.cs
- SqlConnectionString.cs
- DataGridViewControlCollection.cs
- ResourceReader.cs
- Set.cs
- versioninfo.cs
- ICollection.cs
- Adorner.cs
- LongValidator.cs
- AtomPub10ServiceDocumentFormatter.cs
- DataServiceQueryProvider.cs
- KnownIds.cs
- EntityViewGenerationConstants.cs
- PackWebRequest.cs
- __ComObject.cs
- ReadOnlyDataSource.cs
- ExpressionEditorAttribute.cs
- Frame.cs
- WmlPhoneCallAdapter.cs
- TableCellCollection.cs
- InsufficientMemoryException.cs
- MobileUITypeEditor.cs
- EntityKeyElement.cs
- ApplicationBuildProvider.cs
- EncryptedReference.cs
- DataSourceCacheDurationConverter.cs
- TableLayoutCellPaintEventArgs.cs
- RecordBuilder.cs
- TextClipboardData.cs
- RC2.cs
- MemberAccessException.cs
- DurableInstanceContextProvider.cs
- ParallelLoopState.cs
- DataSourceHelper.cs
- WizardDesigner.cs
- KeyPullup.cs
- InternalDuplexChannelFactory.cs
- DesignerActionItemCollection.cs
- PerformanceCountersElement.cs
- BaseConfigurationRecord.cs
- OpenFileDialog.cs
- EventHandlerService.cs
- _LazyAsyncResult.cs
- ZoneButton.cs
- WebContext.cs
- ConfigurationStrings.cs
- ProtectedProviderSettings.cs
- SoapSchemaMember.cs
- SerializationEventsCache.cs
- Label.cs
- TreeBuilderBamlTranslator.cs
- LinqDataSourceInsertEventArgs.cs
- WithParamAction.cs
- LocalBuilder.cs
- DbTransaction.cs
- ProviderSettingsCollection.cs
- InputProcessorProfiles.cs
- EnvironmentPermission.cs
- XPathEmptyIterator.cs
- LongTypeConverter.cs
- DispatchOperationRuntime.cs
- SubstitutionList.cs
- InvalidCardException.cs
- XsdDateTime.cs
- BrowserCapabilitiesFactory.cs
- SectionXmlInfo.cs
- SerializerDescriptor.cs
- SiteOfOriginContainer.cs
- _ListenerResponseStream.cs
- ButtonRenderer.cs
- HttpCachePolicyWrapper.cs
- NativeCppClassAttribute.cs
- GenericTextProperties.cs
- RoutingTable.cs
- RtfToXamlLexer.cs
- ToolStripSeparatorRenderEventArgs.cs
- EmbeddedMailObject.cs
- _ListenerAsyncResult.cs
- ImmComposition.cs
- SafeEventLogReadHandle.cs
- EmissiveMaterial.cs
- Thickness.cs