File: System\Activities\XamlIntegration\TextExpressionCompiler.cs
Project: ndp\cdf\src\NetFx40\System.Activities\System.Activities.csproj (System.Activities)
//-----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------------------------
 
namespace System.Activities.XamlIntegration
{
    using System;
    using System.Text;
    using System.Activities;
    using System.Activities.Statements;
    using System.Activities.Validation;
    using System.Reflection;
    using System.CodeDom;
    using System.CodeDom.Compiler;
    using System.ComponentModel;
    using System.Collections.Generic;
    using Microsoft.VisualBasic.Activities;
    using Microsoft.VisualBasic;
    using System.Windows.Markup;
    using System.Xaml;
    using System.Activities.Debugger;
    using System.IO;
    using System.Activities.Expressions;
    using System.Runtime;
    using System.Diagnostics.CodeAnalysis;
    using System.Security;
    using System.Security.Permissions;
    using System.Globalization;
    using System.Activities.Debugger.Symbol;
    using System.Linq.Expressions;
    using System.Diagnostics;
 
    public class TextExpressionCompiler
    {
        static string typedDataContextName = "_TypedDataContext";
        static string expressionGetString = "__Expr{0}Get";
        static string expressionSetString = "__Expr{0}Set";
        static string expressionStatementString = "__Expr{0}Statement";
        static string expressionGetTreeString = "__Expr{0}GetTree";
        static string getValueTypeValuesString = "GetValueTypeValues";
        static string setValueTypeValuesString = "SetValueTypeValues";
        static string valueTypeAccessorString = "ValueType_";
        static string forReadOnly = "_ForReadOnly";
        static string xamlIntegrationNamespace = "System.Activities.XamlIntegration";
        static string rootActivityFieldName = "rootActivity";
        static string dataContextActivitiesFieldName = "dataContextActivities";
        static string forImplementationName = "forImplementation";
        static CodeAttributeDeclaration generatedCodeAttribute;
        static CodeAttributeDeclaration browsableCodeAttribute;
        static CodeAttributeDeclaration editorBrowsableCodeAttribute;
        static string csharpLambdaString = "() => ";
        static string vbLambdaString = "Function() ";
        static string locationsOffsetFieldName = "locationsOffset";
        static string expectedLocationsCountFieldName = "expectedLocationsCount";
 
        Dictionary<int, IList<string>> expressionIdToLocationReferences = new Dictionary<int, IList<string>>();
 
        string activityFullName;
        int nextContextId;
        bool? isCS = null;
        bool? isVB = null;
        bool generateSource;
 
        TextExpressionCompilerSettings settings;
        
        List<CompiledExpressionDescriptor> expressionDescriptors;
        Stack<CompiledDataContextDescriptor> compiledDataContexts;
 
        CodeNamespace codeNamespace;
        CodeTypeDeclaration classDeclaration;
        CodeCompileUnit compileUnit;
 
        Dictionary<object, SourceLocation> symbols = null;
        string fileName = null;
 
        // Dictionary of namespace name => [Line#]
        Dictionary<string, int> lineNumbersForNSes;
        Dictionary<string, int> lineNumbersForNSesForImpl;
 
        public TextExpressionCompiler(TextExpressionCompilerSettings settings)
        {
            if (settings == null)
            {
                throw FxTrace.Exception.ArgumentNull("settings");
            }
 
            if (settings.Activity == null)
            {
                throw FxTrace.Exception.Argument("settings", SR.TextExpressionCompilerActivityRequired);
            }
 
            if (settings.ActivityName == null)
            {
                throw FxTrace.Exception.Argument("settings", SR.TextExpressionCompilerActivityNameRequired);
            }
 
            if (settings.Language == null)
            {
                throw FxTrace.Exception.Argument("settings", SR.TextExpressionCompilerLanguageRequired);
            }
 
            this.expressionDescriptors = new List<CompiledExpressionDescriptor>();
            this.compiledDataContexts = new Stack<CompiledDataContextDescriptor>();
            this.nextContextId = 0;
 
            this.settings = settings;
 
            this.activityFullName = activityFullName = GetActivityFullName(settings);
 
            this.generateSource = this.settings.AlwaysGenerateSource;
 
            this.lineNumbersForNSes = new Dictionary<string, int>();
            this.lineNumbersForNSesForImpl = new Dictionary<string, int>();
        }        
 
        bool IsCS
        {
            get
            {
                if (!isCS.HasValue)
                {
                    isCS = TextExpression.LanguagesAreEqual(this.settings.Language, "C#");
                }
                return isCS.Value;
            }
        }
 
        bool IsVB
        {
            get
            {
                if (!isVB.HasValue)
                {
                    isVB = TextExpression.LanguagesAreEqual(this.settings.Language, "VB");
                }
                return isVB.Value;
            }
        }
 
        bool InVariableScopeArgument
        {
            get;
            set;
        }
 
        static CodeAttributeDeclaration GeneratedCodeAttribute
        {
            get
            {
                if (generatedCodeAttribute == null)
                {
                    AssemblyName currentAssemblyName = new AssemblyName(Assembly.GetExecutingAssembly().FullName);
                    generatedCodeAttribute = new CodeAttributeDeclaration(
                        new CodeTypeReference(typeof(GeneratedCodeAttribute)),
                        new CodeAttributeArgument(new CodePrimitiveExpression(currentAssemblyName.Name)),
                        new CodeAttributeArgument(new CodePrimitiveExpression(currentAssemblyName.Version.ToString())));
                }
 
                return generatedCodeAttribute;
            }
        }
 
        static CodeAttributeDeclaration BrowsableCodeAttribute
        {
            get
            {
                if (browsableCodeAttribute == null)
                {
                   browsableCodeAttribute = new CodeAttributeDeclaration(
                       new CodeTypeReference(typeof(BrowsableAttribute)),
                       new CodeAttributeArgument(new CodePrimitiveExpression(false)));
                }
                return browsableCodeAttribute;
            }
        }
 
        static CodeAttributeDeclaration EditorBrowsableCodeAttribute
        {
            get
            {
                if (editorBrowsableCodeAttribute == null)
                {
                    editorBrowsableCodeAttribute = new CodeAttributeDeclaration(
                        new CodeTypeReference(typeof(EditorBrowsableAttribute)),
                        new CodeAttributeArgument(new CodeFieldReferenceExpression(
                            new CodeTypeReferenceExpression(
                            new CodeTypeReference(typeof(EditorBrowsableState))), "Never")));
                }
                return editorBrowsableCodeAttribute;
            }
        }
 
                
        public bool GenerateSource(TextWriter textWriter)
        {
            if (textWriter == null)
            {
                throw FxTrace.Exception.ArgumentNull("textWriter");
            }
 
            Parse();
 
            if (this.generateSource)
            {
                WriteCode(textWriter);
                return true;
            }
 
            return false;
        }
 
        public TextExpressionCompilerResults Compile()
        {
            Parse();
 
            if (this.generateSource)
            {
                return CompileInMemory();
            }
 
            return new TextExpressionCompilerResults();
        }
        
        void Parse()
        {                    
            if (!this.settings.Activity.IsMetadataCached)
            {
                IList<ValidationError> validationErrors = null;
                try
                {
                    ActivityUtilities.CacheRootMetadata(this.settings.Activity, new ActivityLocationReferenceEnvironment(), ProcessActivityTreeOptions.FullCachingOptions, null, ref validationErrors);
                }
                catch (Exception e)
                {
                    if (Fx.IsFatal(e))
                    {
                        throw;
                    }
 
                    throw FxTrace.Exception.AsError(new InvalidOperationException(SR.CompiledExpressionsCacheMetadataException(this.settings.Activity.GetType().AssemblyQualifiedName, e.ToString())));
                }
            }
 
            // Get the source location for an activity             
            if (this.TryGetSymbols(this.settings.Activity, out this.symbols, out this.fileName))
            {
                // Get line number info for namespaces
                TextExpressionCompilerHelper.GetNamespacesLineInfo(this.fileName, this.lineNumbersForNSes, this.lineNumbersForNSesForImpl);
            }
           
            this.compileUnit = new CodeCompileUnit();
            this.codeNamespace = GenerateCodeNamespace();
            this.classDeclaration = GenerateClass();
 
            this.codeNamespace.Types.Add(classDeclaration);
            this.compileUnit.Namespaces.Add(this.codeNamespace);
 
            //
            // Generate data contexts with properties and expression methods
            // Use the shared, public tree walk for expressions routine for consistency.       
            ExpressionCompilerActivityVisitor visitor = new ExpressionCompilerActivityVisitor(this)
            {
                NextExpressionId = 0,
            };
 
            try
            {
                visitor.Visit(this.settings.Activity, this.settings.ForImplementation);
            }
            catch (Exception e)
            {
                if (Fx.IsFatal(e))
                {
                    throw;
                }
                //
                // Note that unlike the above where the exception from CacheMetadata is always going to be from the user's code 
                // an exception here is more likely to be from our code and unexpected.  However it could be from user code in some cases.
                // Output a message that attempts to normalize this and presents enough info to the user to determine if they can take action.                
                throw FxTrace.Exception.AsError(new InvalidOperationException(SR.CompiledExpressionsActivityException(e.GetType().FullName, this.settings.Activity.GetType().AssemblyQualifiedName, e.ToString())));
            }
 
            if (this.generateSource)
            {
                GenerateInvokeExpressionMethod(true);
                GenerateInvokeExpressionMethod(false);
 
                GenerateCanExecuteMethod();
 
                GenerateGetRequiredLocationsMethod();
 
                GenerateGetExpressionTreeForExpressionMethod();
            }
 
        }
 
        void OnRootActivity()
        {
            //
            // Always generate a CDC for the root
            // This will contain expressions for the default value of the root arguments
            // These expressions cannot see other root arguments or variables so they need 
            // to be at the very root, before we add any properties
            PushDataContextDescriptor();
        }
 
        void OnAfterRootActivity()
        {
            //
            // First pop the root arguments descriptor pushed in OnAfterRootArguments
            PopDataContextDescriptor();
            //
            // If we are walking the implementation there will be a second root context descriptor
            // that holds the member declarations for root arguments.   
            // This isn't generatedwhen walking the public surface
            if (this.settings.ForImplementation)
            {
                PopDataContextDescriptor();
            }
        }
                
        void OnAfterRootArguments(Activity activity)
        {
            //
            // Generate the properties for root arguments in a context below the context
            // that contains the default expressions for the root arguments
            CompiledDataContextDescriptor contextDescriptor = PushDataContextDescriptor();
            if (activity.RuntimeArguments != null && activity.RuntimeArguments.Count > 0)
            {
                //
                // Walk the arguments
                foreach (RuntimeArgument runtimeArgument in activity.RuntimeArguments)
                {
                    if (runtimeArgument.IsBound)
                    {
                        AddMember(runtimeArgument.Name, runtimeArgument.Type, contextDescriptor);
                    }
                }
            }
        }
       
        void OnActivityDelegateScope()
        {
            PushDataContextDescriptor();
        }
 
        void OnDelegateArgument(RuntimeDelegateArgument delegateArgument)
        {
            AddMember(delegateArgument.BoundArgument.Name, delegateArgument.BoundArgument.Type, this.compiledDataContexts.Peek());
        }
 
        void OnAfterActivityDelegateScope()
        {
            PopDataContextDescriptor();
        }
        
        void OnVariableScope(Activity activity)
        {
            CompiledDataContextDescriptor contextDescriptor = PushDataContextDescriptor();
            //
            // Generate the variable accessors
            foreach (Variable v in activity.RuntimeVariables)
            {
                AddMember(v.Name, v.Type, contextDescriptor);
            }
        }
 
        void OnRootImplementationScope(Activity activity, out CompiledDataContextDescriptor rootArgumentAccessorContext)
        {
            Fx.Assert(this.compiledDataContexts.Count == 2, "The stack of data contexts should contain the root argument default expression and accessor contexts");
 
            rootArgumentAccessorContext = this.compiledDataContexts.Pop();
 
            if (activity.RuntimeVariables != null && activity.RuntimeVariables.Count > 0)
            {
                this.OnVariableScope(activity);
            }
        }
 
        void OnAfterRootImplementationScope(Activity activity, CompiledDataContextDescriptor rootArgumentAccessorContext)
        {
            if (activity.RuntimeVariables != null && activity.RuntimeVariables.Count > 0)
            {
                OnAfterVariableScope();
            }
 
            this.compiledDataContexts.Push(rootArgumentAccessorContext);
        }
 
        void AddMember(string name, Type type, CompiledDataContextDescriptor contextDescriptor)
        {
            if (IsValidTextIdentifierName(name))
            {
                //
                // These checks will be invariantlowercase if the language is VB
                if (contextDescriptor.Fields.ContainsKey(name) || contextDescriptor.Properties.ContainsKey(name))
                {
                    if (!contextDescriptor.Duplicates.Contains(name))
                    {
                        contextDescriptor.Duplicates.Add(name.ToUpperInvariant());
                    }
                }
                else
                {
                    MemberData memberData = new MemberData();
                    memberData.Type = type;
                    memberData.Name = name;
                    memberData.Index = contextDescriptor.NextMemberIndex;
 
                    if (type.IsValueType)
                    {
                        contextDescriptor.Fields.Add(name, memberData);
                    }
                    else
                    {
                        contextDescriptor.Properties.Add(name, memberData);
                    }
                }
            }
            //
            // Regardless of whether or not this member name is an invalid, duplicate, or valid identifier
            // always increment the member count so that the indexes we generate always match
            // the list that the runtime gives to the ITextExpression
            // The exception here is if the name is null
            if (name != null)
            {
                contextDescriptor.NextMemberIndex++;
            }
        }
 
        void GenerateMembers(CompiledDataContextDescriptor descriptor)
        {
            foreach (KeyValuePair<string, MemberData> property in descriptor.Properties)
            {
                GenerateProperty(property.Value, descriptor);
            }
 
            if (descriptor.Fields.Count > 0)
            {
                foreach (KeyValuePair<string, MemberData> field in descriptor.Fields)
                {
                    GenerateField(field.Value, descriptor);
                }
 
                CodeMemberMethod getValueTypeValuesMethod = GenerateGetValueTypeValues(descriptor);
 
                descriptor.CodeTypeDeclaration.Members.Add(getValueTypeValuesMethod);
                descriptor.CodeTypeDeclaration.Members.Add(GenerateSetValueTypeValues(descriptor));
 
                descriptor.CodeTypeDeclarationForReadOnly.Members.Add(getValueTypeValuesMethod);
            }
 
            if (descriptor.Duplicates.Count > 0 && this.IsVB)
            {
                foreach (string duplicate in descriptor.Duplicates)
                {
                    AddPropertyForDuplicates(duplicate, descriptor);
                }
            }
        }
 
        void GenerateField(MemberData memberData, CompiledDataContextDescriptor contextDescriptor)
        {
            if (contextDescriptor.Duplicates.Contains(memberData.Name))
            {
                return;
            }
 
            CodeMemberField accessorField = new CodeMemberField();
            accessorField.Attributes = MemberAttributes.Family | MemberAttributes.Final;
            accessorField.Name = memberData.Name;
            accessorField.Type = new CodeTypeReference(memberData.Type);
 
            if (IsRedefinition(memberData.Name))
            {
                accessorField.Attributes |= MemberAttributes.New;
            }
 
            contextDescriptor.CodeTypeDeclaration.Members.Add(accessorField);
 
            contextDescriptor.CodeTypeDeclarationForReadOnly.Members.Add(accessorField);
        }
 
        void GenerateProperty(MemberData memberData, CompiledDataContextDescriptor contextDescriptor)
        {
            if (contextDescriptor.Duplicates.Contains(memberData.Name))
            {
                return;
            }
 
            bool isRedefinition = IsRedefinition(memberData.Name);
 
            CodeMemberProperty accessorProperty = GenerateCodeMemberProperty(memberData, isRedefinition);
 
            //
            // Generate a get accessor that looks like this:
            // return (Foo) this.GetVariableValue(contextId, locationIndexId)
            CodeMethodReturnStatement getterStatement = new CodeMethodReturnStatement(
                new CodeCastExpression(memberData.Type, new CodeMethodInvokeExpression(
                    new CodeMethodReferenceExpression(
                        new CodeThisReferenceExpression(),
                        "GetVariableValue"), 
                        new CodeBinaryOperatorExpression(
                        new CodePrimitiveExpression(memberData.Index), 
                        CodeBinaryOperatorType.Add, 
                        new CodeVariableReferenceExpression("locationsOffset")))));
 
            accessorProperty.GetStatements.Add(getterStatement);
            
            // Generate a set accessor that looks something like this:
            // this.SetVariableValue(contextId, locationIndexId, value)
            accessorProperty.SetStatements.Add(new CodeMethodInvokeExpression(
                new CodeMethodReferenceExpression(
                    new CodeThisReferenceExpression(),
                    "SetVariableValue"),
                     new CodeBinaryOperatorExpression(
                        new CodePrimitiveExpression(memberData.Index),
                        CodeBinaryOperatorType.Add,
                        new CodeVariableReferenceExpression("locationsOffset")),
                    new CodePropertySetValueReferenceExpression()));
 
            contextDescriptor.CodeTypeDeclaration.Members.Add(accessorProperty);
 
            //
            // Create another property for the read only class.
            // This will only have a getter so we can't just re-use the property from above
            CodeMemberProperty accessorPropertyForReadOnly = GenerateCodeMemberProperty(memberData, isRedefinition);
            //
            // OK to share the getter statement from above
            accessorPropertyForReadOnly.GetStatements.Add(getterStatement);
 
            contextDescriptor.CodeTypeDeclarationForReadOnly.Members.Add(accessorPropertyForReadOnly);
        }
 
        CodeMemberProperty GenerateCodeMemberProperty(MemberData memberData, bool isRedefinition)
        {
            CodeMemberProperty accessorProperty = new CodeMemberProperty();
            accessorProperty.Attributes = MemberAttributes.Family | MemberAttributes.Final;
            accessorProperty.Name = memberData.Name;
            accessorProperty.Type = new CodeTypeReference(memberData.Type);
 
            if (isRedefinition)
            {
                accessorProperty.Attributes |= MemberAttributes.New;
            }
 
            return accessorProperty;
        }
 
        void AddPropertyForDuplicates(string name, CompiledDataContextDescriptor contextDescriptor)
        {
            CodeMemberProperty accessorProperty = new CodeMemberProperty();
            accessorProperty.Attributes = MemberAttributes.Family | MemberAttributes.Final;
            accessorProperty.Name = name;
            accessorProperty.Type = new CodeTypeReference(typeof(object));
 
            CodeThrowExceptionStatement exception = new CodeThrowExceptionStatement(
                new CodeObjectCreateExpression(typeof(InvalidOperationException), new CodePrimitiveExpression(SR.CompiledExpressionsDuplicateName(name))));
 
            accessorProperty.GetStatements.Add(exception);
            accessorProperty.SetStatements.Add(exception);
 
            contextDescriptor.CodeTypeDeclaration.Members.Add(accessorProperty);
 
            //
            // Create another property for the read only class.
            // This will only have a getter so we can't just re-use the property from above
            CodeMemberProperty accessorPropertyForReadOnly = new CodeMemberProperty();
            accessorPropertyForReadOnly.Attributes = MemberAttributes.Family | MemberAttributes.Final;
            accessorPropertyForReadOnly.Name = name;
            accessorPropertyForReadOnly.Type = new CodeTypeReference(typeof(object));
            //
            // OK to share the exception from above
            accessorPropertyForReadOnly.GetStatements.Add(exception);
 
            contextDescriptor.CodeTypeDeclarationForReadOnly.Members.Add(accessorPropertyForReadOnly);
        }
 
        [Fx.Tag.SecurityNote(Critical = "Critical because we are accessing CodeDom.",
            Safe = "Safe because we are demanding FullTrust")]
        [SecuritySafeCritical]
        [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
        bool IsValidTextIdentifierName(string name)
        {
            if (string.IsNullOrWhiteSpace(name))
            {
                if (this.settings.LogSourceGenerationMessage != null)
                {
                    this.settings.LogSourceGenerationMessage(SR.CompiledExpressionsIgnoringUnnamedVariable);
                }
                return false;
            }
 
            if (!CodeDomProvider.CreateProvider(this.settings.Language).IsValidIdentifier(name))
            {
                if (this.settings.LogSourceGenerationMessage != null)
                {
                    this.settings.LogSourceGenerationMessage(SR.CompiledExpressionsIgnoringInvalidIdentifierVariable(name));
                }
                return false;
            }
            
            return true;
        }
 
        bool IsRedefinition(string variableName)
        {
            if (this.compiledDataContexts == null)
            {
                return false;
            }
 
            foreach (CompiledDataContextDescriptor contextDescriptor in this.compiledDataContexts)
            {
                foreach (KeyValuePair<string, MemberData> field in contextDescriptor.Fields)
                {
                    if (NamesMatch(variableName, field.Key))
                    {
                        return true;
                    }
                }
                foreach (KeyValuePair<string, MemberData> property in contextDescriptor.Properties)
                {
                    if (NamesMatch(variableName, property.Key))
                    {
                        return true;
                    }
                }
            }
 
            return false;
        }
 
        bool NamesMatch(string toCheck, string current)
        {
            if (IsVB && string.Compare(toCheck, current, true, CultureInfo.CurrentCulture) == 0)
            {
                return true;
            }
            else if (!IsVB && toCheck == current)
            {
                return true;
            }
 
            return false;
        }
 
        void OnAfterVariableScope()
        {
            PopDataContextDescriptor();
        }
 
        void OnITextExpressionFound(Activity activity, ExpressionCompilerActivityVisitor visitor)
        {
            CompiledDataContextDescriptor contextDescriptor = null;
            CompiledDataContextDescriptor currentContextDescriptor = this.compiledDataContexts.Peek();
 
            if (this.InVariableScopeArgument)
            {
                //
                // Temporarily popping the stack so don't use PopDataContextDescriptor
                // because that is for when the descriptor is done being built
                this.compiledDataContexts.Pop();
                contextDescriptor = PushDataContextDescriptor();
            }
            else
            {
                contextDescriptor = currentContextDescriptor;
            }
            
 
            if (TryGenerateExpressionCode(activity, contextDescriptor, visitor.NextExpressionId, this.settings.Language))
            {
                expressionIdToLocationReferences.Add(visitor.NextExpressionId, this.FindLocationReferences(activity));
                visitor.NextExpressionId++;
                this.generateSource = true;
            }
 
            if (this.InVariableScopeArgument)
            {
                PopDataContextDescriptor();
                this.compiledDataContexts.Push(currentContextDescriptor);
            }
        }
 
        IList<string> FindLocationReferences(Activity activity)
        {
            ActivityWithResult boundExpression;
            LocationReference locationReference;
            List<string> requiredLocationReferences = new List<string>();
 
            foreach (RuntimeArgument runtimeArgument in activity.RuntimeArguments)
            {
                boundExpression = runtimeArgument.BoundArgument.Expression;
 
                if (boundExpression != null && boundExpression is ILocationReferenceWrapper)
                {
                    locationReference = ((ILocationReferenceWrapper)boundExpression).LocationReference;
 
                    if (locationReference != null)
                    {
                        requiredLocationReferences.Add(locationReference.Name);
                    }
                }
            }
            return requiredLocationReferences;
        }
 
        CodeTypeDeclaration GenerateClass()
        {
            CodeTypeDeclaration classDeclaration = new CodeTypeDeclaration(this.settings.ActivityName);
            classDeclaration.BaseTypes.Add(new CodeTypeReference(typeof(ICompiledExpressionRoot)));
            classDeclaration.IsPartial = this.settings.GenerateAsPartialClass;
 
            CodeMemberField compiledRootField = new CodeMemberField(new CodeTypeReference(typeof(Activity)), rootActivityFieldName);
            classDeclaration.Members.Add(compiledRootField);
 
            CodeMemberMethod languageProperty = new CodeMemberMethod();
            languageProperty.Attributes = MemberAttributes.Final | MemberAttributes.Public;
            languageProperty.Name = "GetLanguage";
            languageProperty.ReturnType = new CodeTypeReference(typeof(string));
            languageProperty.Statements.Add(new CodeMethodReturnStatement(new CodePrimitiveExpression(this.settings.Language)));
            languageProperty.ImplementationTypes.Add(new CodeTypeReference(typeof(ICompiledExpressionRoot)));            
            languageProperty.CustomAttributes.Add(GeneratedCodeAttribute);
            languageProperty.CustomAttributes.Add(BrowsableCodeAttribute);
            languageProperty.CustomAttributes.Add(EditorBrowsableCodeAttribute);
 
            classDeclaration.Members.Add(languageProperty);
 
            CodeMemberField dataContextActivitiesField = new CodeMemberField();
            dataContextActivitiesField.Attributes = MemberAttributes.Private;
            dataContextActivitiesField.Name = dataContextActivitiesFieldName;
            dataContextActivitiesField.Type = new CodeTypeReference(typeof(object));
 
            classDeclaration.Members.Add(dataContextActivitiesField);
 
            CodeMemberField forImplementationField = new CodeMemberField();
            forImplementationField.Attributes = MemberAttributes.Private;
            forImplementationField.Name = forImplementationName;
            forImplementationField.Type = new CodeTypeReference(typeof(bool));
            forImplementationField.InitExpression = new CodePrimitiveExpression(this.settings.ForImplementation);
 
            classDeclaration.Members.Add(forImplementationField);
 
            if (!this.settings.GenerateAsPartialClass)
            {
                classDeclaration.Members.Add(GenerateCompiledExpressionRootConstructor());
            }
 
            return classDeclaration;
        }
 
        CodeConstructor GenerateCompiledExpressionRootConstructor()
        {
            CodeConstructor constructor = new CodeConstructor();
            constructor.Attributes = MemberAttributes.Public;
 
            constructor.Parameters.Add(
                new CodeParameterDeclarationExpression(
                    new CodeTypeReference(typeof(Activity)),
                    rootActivityFieldName));
 
            CodeBinaryOperatorExpression nullArgumentExpression = new CodeBinaryOperatorExpression(
                new CodeVariableReferenceExpression(rootActivityFieldName),
                CodeBinaryOperatorType.IdentityEquality,
                new CodePrimitiveExpression(null));
 
            CodeConditionStatement nullArgumentCondition = new CodeConditionStatement(
                nullArgumentExpression,
                new CodeThrowExceptionStatement(
                    new CodeObjectCreateExpression(
                        new CodeTypeReference(typeof(ArgumentNullException)),
                        new CodePrimitiveExpression(rootActivityFieldName))));
 
            constructor.Statements.Add(nullArgumentCondition);
 
            constructor.Statements.Add(
                new CodeAssignStatement(
                    new CodeFieldReferenceExpression(
                        new CodeThisReferenceExpression(),
                        rootActivityFieldName),
                    new CodeVariableReferenceExpression(rootActivityFieldName)));
 
            return constructor;
        }
 
        Dictionary<string, int> GetCacheIndicies()
        {
            Dictionary<string, int> contexts = new Dictionary<string, int>();
            int currentIndex = 0;
 
            foreach (CompiledExpressionDescriptor descriptor in this.expressionDescriptors)
            {
                string name = descriptor.TypeName;
                if (!contexts.ContainsKey(name))
                {
                    contexts.Add(name, currentIndex++);
                }
            }
 
            return contexts;
        }
 
        void GenerateGetRequiredLocationsMethod()
        {
            CodeMemberMethod getLocationsMethod = new CodeMemberMethod();
            getLocationsMethod.Name = "GetRequiredLocations";
            getLocationsMethod.Attributes = MemberAttributes.Final | MemberAttributes.Public;
            getLocationsMethod.CustomAttributes.Add(GeneratedCodeAttribute);
            getLocationsMethod.CustomAttributes.Add(BrowsableCodeAttribute);
            getLocationsMethod.CustomAttributes.Add(EditorBrowsableCodeAttribute);
            getLocationsMethod.ImplementationTypes.Add(new CodeTypeReference(typeof(ICompiledExpressionRoot)));
 
            getLocationsMethod.ReturnType = new CodeTypeReference(typeof(IList<string>));
 
            getLocationsMethod.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference(typeof(int)), "expressionId"));
 
            if (this.IsVB)
            {
                GenerateRequiredLocationsBody(getLocationsMethod);
            }
            else
            {
                GenerateEmptyRequiredLocationsBody(getLocationsMethod);
            }
 
            classDeclaration.Members.Add(getLocationsMethod);
        }
 
        void GenerateEmptyRequiredLocationsBody(CodeMemberMethod getLocationsMethod)
        {
            getLocationsMethod.Statements.Add(new CodeMethodReturnStatement(new CodePrimitiveExpression(null)));
        }
 
        void GenerateRequiredLocationsBody(CodeMemberMethod getLocationsMethod)
        {
            CodeVariableDeclarationStatement returnLocationsVar = new CodeVariableDeclarationStatement(new CodeTypeReference(typeof(List<string>)),
                "returnLocations",
                new CodeObjectCreateExpression(new CodeTypeReference(typeof(List<string>))));
 
            getLocationsMethod.Statements.Add(returnLocationsVar);
            foreach (CompiledExpressionDescriptor descriptor in expressionDescriptors)
            {
                IList<string> requiredLocations = null;
                bool found = expressionIdToLocationReferences.TryGetValue(descriptor.Id, out requiredLocations);
                if (!found)
                {
                    return;
                }
                CodeStatement[] conditionStatements = null;
                conditionStatements = GetRequiredLocationsConditionStatements(requiredLocations);
 
                CodeBinaryOperatorExpression idExpression = new CodeBinaryOperatorExpression(new CodeVariableReferenceExpression("expressionId"), CodeBinaryOperatorType.ValueEquality, new CodePrimitiveExpression(descriptor.Id));
                CodeConditionStatement idCondition = new CodeConditionStatement(idExpression, conditionStatements);
 
                getLocationsMethod.Statements.Add(idCondition);
            }
 
            getLocationsMethod.Statements.Add(new CodeMethodReturnStatement(new CodeVariableReferenceExpression("returnLocations")));
        }
 
        static CodeStatement[] GetRequiredLocationsConditionStatements(IList<string> requiredLocations)
        {
            CodeStatementCollection statementCollection = new CodeStatementCollection();
            foreach (string locationName in requiredLocations)
            {
                CodeMethodInvokeExpression invokeValidateExpression = new CodeMethodInvokeExpression(
                new CodeMethodReferenceExpression(new CodeVariableReferenceExpression("returnLocations"), "Add"),
                new CodePrimitiveExpression(locationName));
                statementCollection.Add(invokeValidateExpression);
            }
 
            CodeStatement[] returnStatements = new CodeStatement[statementCollection.Count];
            statementCollection.CopyTo(returnStatements, 0);
 
            return returnStatements;
        }
 
        void GenerateGetExpressionTreeForExpressionMethod()
        {
            CodeMemberMethod getExpressionTreeForExpressionMethod = new CodeMemberMethod();
            getExpressionTreeForExpressionMethod.Name = "GetExpressionTreeForExpression";
            getExpressionTreeForExpressionMethod.Attributes = MemberAttributes.Final | MemberAttributes.Public;
            getExpressionTreeForExpressionMethod.ReturnType = new CodeTypeReference(typeof(Expression));
            getExpressionTreeForExpressionMethod.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference(typeof(int)), "expressionId"));
            getExpressionTreeForExpressionMethod.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference(typeof(IList<LocationReference>)), "locationReferences"));
            getExpressionTreeForExpressionMethod.ImplementationTypes.Add(new CodeTypeReference(typeof(ICompiledExpressionRoot)));
            
            // Mark this type as tool generated code
            getExpressionTreeForExpressionMethod.CustomAttributes.Add(GeneratedCodeAttribute);
 
            // Mark it as Browsable(false) 
            // Note that this does not prevent intellisense within a single project, just at the metadata level
            getExpressionTreeForExpressionMethod.CustomAttributes.Add(BrowsableCodeAttribute);
 
            // Mark it as EditorBrowsable(EditorBrowsableState.Never)
            // Note that this does not prevent intellisense within a single project, just at the metadata level
            getExpressionTreeForExpressionMethod.CustomAttributes.Add(EditorBrowsableCodeAttribute);
 
            foreach (CompiledExpressionDescriptor descriptor in expressionDescriptors)
            {
                CodeMethodReturnStatement conditionStatement = new CodeMethodReturnStatement(
                    new CodeMethodInvokeExpression(
                        new CodeMethodReferenceExpression(
                            new CodeObjectCreateExpression(new CodeTypeReference(descriptor.TypeName), new CodeExpression[] { new CodeVariableReferenceExpression("locationReferences") }),
                            descriptor.GetExpressionTreeMethodName)));
 
                CodeBinaryOperatorExpression idExpression = new CodeBinaryOperatorExpression(new CodeVariableReferenceExpression("expressionId"), CodeBinaryOperatorType.ValueEquality, new CodePrimitiveExpression(descriptor.Id));
                CodeConditionStatement idCondition = new CodeConditionStatement(idExpression, conditionStatement);
 
                getExpressionTreeForExpressionMethod.Statements.Add(idCondition);
            }
 
            getExpressionTreeForExpressionMethod.Statements.Add(new CodeMethodReturnStatement(
                    new CodePrimitiveExpression(null)));
 
            classDeclaration.Members.Add(getExpressionTreeForExpressionMethod);
        }
 
        void GenerateInvokeExpressionMethod(bool withLocationReferences)
        {
            CodeMemberMethod invokeExpressionMethod = new CodeMemberMethod();
            invokeExpressionMethod.Name = "InvokeExpression";
            invokeExpressionMethod.Attributes = MemberAttributes.Final | MemberAttributes.Public;
            invokeExpressionMethod.CustomAttributes.Add(GeneratedCodeAttribute);
            invokeExpressionMethod.CustomAttributes.Add(BrowsableCodeAttribute);
            invokeExpressionMethod.CustomAttributes.Add(EditorBrowsableCodeAttribute);
            invokeExpressionMethod.ImplementationTypes.Add(new CodeTypeReference(typeof(ICompiledExpressionRoot)));
 
            invokeExpressionMethod.ReturnType = new CodeTypeReference(typeof(object));
            
            invokeExpressionMethod.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference(typeof(int)), "expressionId"));
 
            if (withLocationReferences)
            {
                invokeExpressionMethod.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference(typeof(IList<LocationReference>)), "locations"));
                invokeExpressionMethod.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference(typeof(ActivityContext)), "activityContext"));
            }
            else
            {
                invokeExpressionMethod.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference(typeof(IList<Location>)), "locations"));
            }
 
            if (this.settings.GenerateAsPartialClass)
            {
                invokeExpressionMethod.Statements.Add(GenerateInitializeDataContextActivity());
            }
 
            if (withLocationReferences)
            {
                if (this.expressionDescriptors != null && this.expressionDescriptors.Count > 0)
                {
                    //
                    // We only generate the helper method on the root data context/context 0
                    // No need to have it on all contexts.  This is just a slight of hand
                    // so that we don't need to make GetDataContextActivities public on CompiledDataContext.
                    invokeExpressionMethod.Statements.Add(GenerateDataContextActivitiesCheck(this.expressionDescriptors[0]));
                }
            }
 
            Dictionary<string, int> cacheIndicies = GetCacheIndicies();
                        
            foreach (CompiledExpressionDescriptor descriptor in expressionDescriptors)
            {
                //
                // if ((expressionId == [descriptor.Id]))
                // {
                //   if (!CheckExpressionText(expressionId, activityContext)
                //   {
                //     throw new Exception();
                //   }
                //   System.Activities.XamlIntegration.CompiledDataContext[] cachedCompiledDataContext = Workflow1_TypedDataContext1_ForReadOnly.GetCompiledDataContextCacheHelper(this, activityContext, 1);
                //   if ((cachedCompiledDataContext[0] == null))
                //   {
                //     cachedCompiledDataContext[0] = new Workflow1_TypedDataContext1_ForReadOnly(locations, activityContext);
                //   }
                //   Workflow1_TypedDataContext1_ForReadOnly valDataContext0 = ((Workflow1_TypedDataContext1_ForReadOnly)(cachedCompiledDataContext[0]));
                //   return valDataContext0.ValueType___Expr0Get();
                // }
                //
                CodeStatement[] conditionStatements = null;
                if (descriptor.IsReference)
                {
                    conditionStatements = GenerateReferenceExpressionInvocation(descriptor, withLocationReferences, cacheIndicies);
                }
                else if (descriptor.IsValue)
                {
                    conditionStatements = GenerateValueExpressionInvocation(descriptor, withLocationReferences, cacheIndicies);
                }
                else if (descriptor.IsStatement)
                {
                    conditionStatements = GenerateStatementInvocation(descriptor, withLocationReferences, cacheIndicies);
                }
 
                CodeBinaryOperatorExpression idExpression = new CodeBinaryOperatorExpression(new CodeVariableReferenceExpression("expressionId"), CodeBinaryOperatorType.ValueEquality, new CodePrimitiveExpression(descriptor.Id));
                CodeConditionStatement idCondition = new CodeConditionStatement(idExpression, conditionStatements);
 
                invokeExpressionMethod.Statements.Add(idCondition);
            }
 
            invokeExpressionMethod.Statements.Add(new CodeMethodReturnStatement(
                    new CodePrimitiveExpression(null)));
 
            classDeclaration.Members.Add(invokeExpressionMethod);
        }
 
        CodeConditionStatement GenerateDataContextActivitiesCheck(CompiledExpressionDescriptor descriptor)
        {
            CodeBinaryOperatorExpression dataContextActivitiesNullExpression = new CodeBinaryOperatorExpression(
                       new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), dataContextActivitiesFieldName),
                       CodeBinaryOperatorType.IdentityEquality,
                       new CodePrimitiveExpression(null));
 
            CodeConditionStatement dataContextActivitiesNullStatement = new CodeConditionStatement(
                dataContextActivitiesNullExpression,
                new CodeAssignStatement(
                    new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), dataContextActivitiesFieldName),
                    new CodeMethodInvokeExpression(
                        new CodeMethodReferenceExpression(
                            new CodeTypeReferenceExpression(new CodeTypeReference(descriptor.TypeName)),
                            "GetDataContextActivitiesHelper"),
                        new CodeFieldReferenceExpression(
                            new CodeThisReferenceExpression(),
                            rootActivityFieldName),
                        new CodeFieldReferenceExpression(
                            new CodeThisReferenceExpression(),
                            forImplementationName))));
 
            return dataContextActivitiesNullStatement;
        }
 
 
        CodeStatement GenerateInitializeDataContextActivity()
        {
            //
            // if (this.rootActivity == null)
            // {
            //   this.rootActivity == this;
            // }
            CodeBinaryOperatorExpression dataContextActivityExpression = new CodeBinaryOperatorExpression(
                new CodeFieldReferenceExpression(
                    new CodeThisReferenceExpression(),
                    rootActivityFieldName),
                CodeBinaryOperatorType.IdentityEquality,
                new CodePrimitiveExpression(null));
 
            CodeConditionStatement dataContextActivityCheck = new CodeConditionStatement(
                dataContextActivityExpression,
                new CodeAssignStatement(
                    new CodeFieldReferenceExpression(
                        new CodeThisReferenceExpression(),
                        rootActivityFieldName),
                    new CodeThisReferenceExpression()));
 
            return dataContextActivityCheck;
        }
 
        void GenerateGetDataContextVariable(CompiledExpressionDescriptor descriptor, CodeVariableDeclarationStatement dataContextVariable, CodeStatementCollection statements, bool withLocationReferences, Dictionary<string, int> cacheIndicies)
        {
            CodeObjectCreateExpression dataContext = GenerateDataContextCreateExpression(descriptor.TypeName, withLocationReferences);
 
            if (withLocationReferences)
            {
                //
                // System.Activities.XamlIntegration.CompiledDataContext[] cachedCompiledDataContext = CompiledExpressions_TypedDataContext2.GetCompiledDataContextCacheHelper(this, activityContext, 2);
                // if ((cachedCompiledDataContext[1] == null))
                // {
                //   if (!CompiledExpressions_TypedDataContext2.Validate(locations, activityContext))
                //   {
                //     return false;
                //   }
                //   cachedCompiledDataContext[1] = new CompiledExpressions_TypedDataContext2(locations, activityContext);
                // }
                //
                CodeVariableDeclarationStatement cachedCompiledDataContextArray = new CodeVariableDeclarationStatement(
                    typeof(CompiledDataContext[]),
                    "cachedCompiledDataContext",
                    new CodeMethodInvokeExpression(
                        new CodeMethodReferenceExpression(
                            new CodeTypeReferenceExpression(descriptor.TypeName),
                            "GetCompiledDataContextCacheHelper"),
                        new CodeFieldReferenceExpression(
                            new CodeThisReferenceExpression(),
                            dataContextActivitiesFieldName),
                        new CodeVariableReferenceExpression("activityContext"),
                        new CodeFieldReferenceExpression(
                            new CodeThisReferenceExpression(),
                            rootActivityFieldName),
                        new CodeFieldReferenceExpression(
                            new CodeThisReferenceExpression(),
                            forImplementationName),
                        new CodePrimitiveExpression(cacheIndicies.Count)));
 
                CodeIndexerExpression compiledDataContextIndexer = new CodeIndexerExpression(
                    new CodeVariableReferenceExpression("cachedCompiledDataContext"),
                    new CodePrimitiveExpression(cacheIndicies[descriptor.TypeName]));
 
                //
                // if (cachedCompiledDataContext[index] == null)
                // {
                //     cachedCompiledDataContext[index] = new TCDC(locations, activityContext);
                // }
                //
 
                CodeBinaryOperatorExpression nullCacheItemExpression = new CodeBinaryOperatorExpression(
                    compiledDataContextIndexer,
                    CodeBinaryOperatorType.IdentityEquality,
                    new CodePrimitiveExpression(null));
 
                CodeAssignStatement cacheIndexInitializer = new CodeAssignStatement(
                    compiledDataContextIndexer,
                    dataContext);
 
                CodeConditionStatement conditionStatement = new CodeConditionStatement(
                    nullCacheItemExpression,
                    cacheIndexInitializer);
                       
                //
                // [compiledDataContextVariable] = cachedCompiledDataContext[index]
                //
 
                dataContextVariable.InitExpression = new CodeCastExpression(descriptor.TypeName, compiledDataContextIndexer);
 
 
                statements.Add(cachedCompiledDataContextArray);
                statements.Add(conditionStatement);
            }
            else
            {
                //
                // [compiledDataContextVariable] = new [compiledDataContextType](locations);
                //
 
                dataContextVariable.InitExpression = dataContext;
            }
        }
 
        CodeStatement[] GenerateReferenceExpressionInvocation(CompiledExpressionDescriptor descriptor, bool withLocationReferences, Dictionary<string, int> cacheIndicies)
        {
            string indexString = descriptor.Id.ToString(CultureInfo.InvariantCulture);
            string dataContextVariableName = "refDataContext" + indexString;
 
            CodeVariableDeclarationStatement dataContextVariable = new CodeVariableDeclarationStatement(
                     new CodeTypeReference(descriptor.TypeName), dataContextVariableName);
 
            CodeStatementCollection compiledDataContextStatements = new CodeStatementCollection();
 
            GenerateGetDataContextVariable(descriptor, dataContextVariable, compiledDataContextStatements, withLocationReferences, cacheIndicies);
            compiledDataContextStatements.Add(dataContextVariable);
 
            CodeExpression getExpression = null;
            CodeExpression setExpression = null;
 
            if (this.IsVB)
            {
                getExpression = new CodeDelegateCreateExpression(
                        new CodeTypeReference(descriptor.TypeName),
                        new CodeVariableReferenceExpression(dataContextVariableName),
                        descriptor.GetMethodName);
                setExpression = new CodeDelegateCreateExpression(
                        new CodeTypeReference(descriptor.TypeName),
                        new CodeVariableReferenceExpression(dataContextVariableName),
                        descriptor.SetMethodName);
            }
            else
            {
                getExpression = new CodeMethodReferenceExpression(new CodeVariableReferenceExpression(dataContextVariableName), descriptor.GetMethodName);
                setExpression = new CodeMethodReferenceExpression(new CodeVariableReferenceExpression(dataContextVariableName), descriptor.SetMethodName);
            }
 
            CodeMethodReferenceExpression getLocationMethod = new CodeMethodReferenceExpression(
                new CodeVariableReferenceExpression(dataContextVariableName),
                "GetLocation",
                new CodeTypeReference[] { new CodeTypeReference(descriptor.ResultType) });
 
            CodeExpression[] getLocationParameters = null;
            if (withLocationReferences)
            {
                getLocationParameters = new CodeExpression[] { 
                    getExpression,  
                    setExpression,
                    new CodeVariableReferenceExpression("expressionId"),
                    new CodeFieldReferenceExpression(
                        new CodeThisReferenceExpression(),
                        rootActivityFieldName),
                    new CodeVariableReferenceExpression("activityContext") };
            }
            else
            {
                getLocationParameters = new CodeExpression[] { 
                    getExpression,  
                    setExpression };
            }
 
            CodeMethodInvokeExpression getLocationExpression = new CodeMethodInvokeExpression(
                getLocationMethod,
                getLocationParameters);
 
 
            CodeMethodReturnStatement returnStatement = new CodeMethodReturnStatement(getLocationExpression);
 
            compiledDataContextStatements.Add(returnStatement);
            
            CodeStatement[] returnStatements = new CodeStatement[compiledDataContextStatements.Count];
            compiledDataContextStatements.CopyTo(returnStatements, 0);
 
            return returnStatements;
        }
 
        CodeStatement[] GenerateValueExpressionInvocation(CompiledExpressionDescriptor descriptor, bool withLocationReferences, Dictionary<string, int> cacheIndicies)
        {
            CodeStatementCollection compiledDataContextStatements = new CodeStatementCollection();
 
            string indexString = descriptor.Id.ToString(CultureInfo.InvariantCulture);
            string dataContextVariableName = "valDataContext" + indexString;
 
            CodeVariableDeclarationStatement dataContextVariable = new CodeVariableDeclarationStatement(
                     new CodeTypeReference(descriptor.TypeName), dataContextVariableName);
 
            GenerateGetDataContextVariable(descriptor, dataContextVariable, compiledDataContextStatements, withLocationReferences, cacheIndicies);
            compiledDataContextStatements.Add(dataContextVariable);
 
            CodeMethodInvokeExpression expressionInvoke = new CodeMethodInvokeExpression(
                new CodeMethodReferenceExpression(
                    new CodeVariableReferenceExpression(dataContextVariableName), descriptor.GetMethodName));
 
            CodeMethodReturnStatement returnStatement = new CodeMethodReturnStatement(expressionInvoke);
 
            compiledDataContextStatements.Add(returnStatement);
 
            CodeStatement[] returnStatements = new CodeStatement[compiledDataContextStatements.Count];
            compiledDataContextStatements.CopyTo(returnStatements, 0);
 
            return returnStatements;
        }
 
        CodeStatement[] GenerateStatementInvocation(CompiledExpressionDescriptor descriptor, bool withLocationReferences, Dictionary<string, int> cacheIndicies)
        {
            string indexString = descriptor.Id.ToString(CultureInfo.InvariantCulture);
            string dataContextVariableName = "valDataContext" + indexString;
 
            CodeVariableDeclarationStatement dataContextVariable = new CodeVariableDeclarationStatement(
                     new CodeTypeReference(descriptor.TypeName), dataContextVariableName);
 
            CodeStatementCollection compiledDataContextStatements = new CodeStatementCollection();
 
            GenerateGetDataContextVariable(descriptor, dataContextVariable, compiledDataContextStatements, withLocationReferences, cacheIndicies);
            compiledDataContextStatements.Add(dataContextVariable);
                        
            CodeMethodInvokeExpression expressionInvoke = new CodeMethodInvokeExpression(
                new CodeMethodReferenceExpression(
                    new CodeVariableReferenceExpression(dataContextVariableName), descriptor.StatementMethodName));
            
            CodeMethodReturnStatement returnStatement = new CodeMethodReturnStatement(new CodePrimitiveExpression(null));
 
            compiledDataContextStatements.Add(expressionInvoke);
            compiledDataContextStatements.Add(returnStatement);
 
            CodeStatement[] returnStatements = new CodeStatement[compiledDataContextStatements.Count];
            compiledDataContextStatements.CopyTo(returnStatements, 0);
 
            return returnStatements;
        }
           
        void GenerateCanExecuteMethod()
        {
            CodeMemberMethod isValidMethod = new CodeMemberMethod();
            isValidMethod.Name = "CanExecuteExpression";
            isValidMethod.ReturnType = new CodeTypeReference(typeof(bool));
            isValidMethod.Attributes = MemberAttributes.Public | MemberAttributes.Final;
            isValidMethod.CustomAttributes.Add(GeneratedCodeAttribute);
            isValidMethod.CustomAttributes.Add(BrowsableCodeAttribute);
            isValidMethod.CustomAttributes.Add(EditorBrowsableCodeAttribute);
            isValidMethod.ImplementationTypes.Add(new CodeTypeReference(typeof(ICompiledExpressionRoot)));
 
            isValidMethod.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference(typeof(string)), "expressionText"));
            isValidMethod.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference(typeof(bool)), "isReference"));
            isValidMethod.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference(typeof(IList<LocationReference>)), "locations"));
 
            CodeParameterDeclarationExpression expressionIdParam = new CodeParameterDeclarationExpression(new CodeTypeReference(typeof(int)), "expressionId");
            expressionIdParam.Direction = FieldDirection.Out;
            isValidMethod.Parameters.Add(expressionIdParam);
           
            //
            // if (((isReference == false)
            //              && ((expressionText == [expression text])
            //              && ([data context type name].Validate(locations, true) == true))))
            // {
            //     expressionId = [id for expression text and data context];
            //     return true;
            // }
            // 
            foreach (CompiledExpressionDescriptor descriptor in expressionDescriptors)
            {
                CodeBinaryOperatorExpression checkIsReferenceExpression = new CodeBinaryOperatorExpression(
                    new CodeVariableReferenceExpression("isReference"),
                    CodeBinaryOperatorType.ValueEquality,
                    new CodePrimitiveExpression(descriptor.IsReference));
 
                CodeBinaryOperatorExpression checkTextExpression = new CodeBinaryOperatorExpression(
                    new CodeVariableReferenceExpression("expressionText"),
                    CodeBinaryOperatorType.ValueEquality,
                    new CodePrimitiveExpression(descriptor.ExpressionText));
 
                CodeMethodInvokeExpression invokeValidateExpression = new CodeMethodInvokeExpression(
                    new CodeMethodReferenceExpression(
                        new CodeTypeReferenceExpression(descriptor.TypeName),
                        "Validate"),
                    new CodeVariableReferenceExpression("locations"),
                    new CodePrimitiveExpression(true),
                    new CodePrimitiveExpression(0));
                
                CodeBinaryOperatorExpression checkValidateExpression = new CodeBinaryOperatorExpression(
                    invokeValidateExpression,
                    CodeBinaryOperatorType.ValueEquality,
                    new CodePrimitiveExpression(true));
 
                CodeBinaryOperatorExpression checkTextAndValidateExpression = new CodeBinaryOperatorExpression(
                    checkTextExpression,
                    CodeBinaryOperatorType.BooleanAnd,
                    checkValidateExpression);
 
                CodeBinaryOperatorExpression checkIsReferenceAndTextAndValidateExpression = new CodeBinaryOperatorExpression(
                    checkIsReferenceExpression,
                    CodeBinaryOperatorType.BooleanAnd,
                    checkTextAndValidateExpression);
                
                CodeAssignStatement assignId = new CodeAssignStatement(
                    new CodeVariableReferenceExpression("expressionId"),
                    new CodePrimitiveExpression(descriptor.Id));
 
                CodeConditionStatement matchCondition = new CodeConditionStatement(
                    checkIsReferenceAndTextAndValidateExpression);
 
                matchCondition.TrueStatements.Add(assignId);
                matchCondition.TrueStatements.Add(new CodeMethodReturnStatement(new CodePrimitiveExpression(true)));
                
                isValidMethod.Statements.Add(matchCondition);
            }
 
            isValidMethod.Statements.Add(
                new CodeAssignStatement(
                    new CodeVariableReferenceExpression("expressionId"),
                    new CodePrimitiveExpression(-1)));
 
            isValidMethod.Statements.Add(
                new CodeMethodReturnStatement(
                    new CodePrimitiveExpression(false)));
 
            classDeclaration.Members.Add(isValidMethod);
        }
 
        CodeObjectCreateExpression GenerateDataContextCreateExpression(string typeName, bool withLocationReferences)
        {
            if (withLocationReferences)
            {
                return new CodeObjectCreateExpression(
                    new CodeTypeReference(typeName),
                    new CodeVariableReferenceExpression("locations"),
                    new CodeVariableReferenceExpression("activityContext"),
                    new CodePrimitiveExpression(true));
            }
            else
            {
                return new CodeObjectCreateExpression(
                    new CodeTypeReference(typeName),
                    new CodeExpression[] { new CodeVariableReferenceExpression("locations"),
                    new CodePrimitiveExpression(true) });
            }
        }
 
        bool TryGenerateExpressionCode(Activity activity, CompiledDataContextDescriptor dataContextDescriptor, int nextExpressionId, string language)
        {
            ITextExpression textExpression = (ITextExpression)activity;
            if (!TextExpression.LanguagesAreEqual(textExpression.Language, language)
                || string.IsNullOrWhiteSpace(textExpression.ExpressionText))
            {
                //
                // We can only compile expressions that match the project's flavor
                // and expression activities with no expressions don't need anything generated.
                return false;
            }
 
            Type resultType = (activity is ActivityWithResult) ? ((ActivityWithResult)activity).ResultType : null;
 
            string expressionText = textExpression.ExpressionText;
                        
            bool isReference = false;
            bool isValue = false;
            bool isStatement = false;
 
            if (resultType == null)
            {
                isStatement = true;
            }
            else
            {
                isReference = TypeHelper.AreTypesCompatible(resultType, typeof(Location));
                isValue = !isReference;
            }
 
            CodeTypeDeclaration typeDeclaration;
            if (isValue)
            {
                typeDeclaration = dataContextDescriptor.CodeTypeDeclarationForReadOnly;
            }
            else
            {
                //
                // Statement and reference get read/write context
                typeDeclaration = dataContextDescriptor.CodeTypeDeclaration;
            }
             
            CompiledExpressionDescriptor descriptor = new CompiledExpressionDescriptor();
            descriptor.TypeName = typeDeclaration.Name;
            descriptor.Id = nextExpressionId;
            descriptor.ExpressionText = textExpression.ExpressionText;
            
            if (isReference)
            {
                if (resultType.IsGenericType)
                {
                    resultType = resultType.GetGenericArguments()[0];
                }
                else
                {
                    resultType = typeof(object);
                }
            }
 
            descriptor.ResultType = resultType;
            
            GenerateExpressionGetTreeMethod(activity, descriptor, dataContextDescriptor, isValue, isStatement, nextExpressionId);
 
            if (isValue || isReference)
            {
                CodeMemberMethod expressionGetMethod = GenerateGetMethod(activity, resultType, expressionText, nextExpressionId);
                typeDeclaration.Members.Add(expressionGetMethod);
 
                CodeMemberMethod expressionGetValueTypeAccessorMethod = GenerateGetMethodWrapper(expressionGetMethod);
                typeDeclaration.Members.Add(expressionGetValueTypeAccessorMethod);
 
                descriptor.GetMethodName = expressionGetValueTypeAccessorMethod.Name;
            }
 
            if (isReference)
            {
                CodeMemberMethod expressionSetMethod = GenerateSetMethod(activity, resultType, expressionText, nextExpressionId);
                dataContextDescriptor.CodeTypeDeclaration.Members.Add(expressionSetMethod);
 
                CodeMemberMethod expressionSetValueTypeAccessorMethod = GenerateSetMethodWrapper(expressionSetMethod);
                dataContextDescriptor.CodeTypeDeclaration.Members.Add(expressionSetValueTypeAccessorMethod);
 
                descriptor.SetMethodName = expressionSetValueTypeAccessorMethod.Name;
            }
 
            if (isStatement)
            {
                CodeMemberMethod statementMethod = GenerateStatementMethod(activity, expressionText, nextExpressionId);
                dataContextDescriptor.CodeTypeDeclaration.Members.Add(statementMethod);
 
                CodeMemberMethod expressionSetValueTypeAccessorMethod = GenerateStatementMethodWrapper(statementMethod);
                dataContextDescriptor.CodeTypeDeclaration.Members.Add(expressionSetValueTypeAccessorMethod);
 
                descriptor.StatementMethodName = expressionSetValueTypeAccessorMethod.Name;
            }
 
            expressionDescriptors.Add(descriptor);
 
            return true;
        }
 
        void GenerateExpressionGetTreeMethod(Activity activity, CompiledExpressionDescriptor expressionDescriptor, CompiledDataContextDescriptor dataContextDescriptor, bool isValue, bool isStatement, int nextExpressionId)
        {
            CodeMemberMethod expressionMethod = new CodeMemberMethod();
            expressionMethod.Attributes = MemberAttributes.Assembly | MemberAttributes.Final;
            expressionMethod.Name = string.Format(CultureInfo.InvariantCulture, expressionGetTreeString, nextExpressionId);
            expressionMethod.ReturnType = new CodeTypeReference(typeof(Expression));
            expressionDescriptor.GetExpressionTreeMethodName = expressionMethod.Name;
 
            if (isStatement)
            {
                // Can't generate expression tree for a statement
                expressionMethod.Statements.Add(new CodeMethodReturnStatement(new CodePrimitiveExpression(null)));
                dataContextDescriptor.CodeTypeDeclaration.Members.Add(expressionMethod);
                return;
            }
 
            string coreExpressionText = expressionDescriptor.ExpressionText;
            CodeLinePragma pragma;
            AlignText(activity, ref coreExpressionText, out pragma);
 
            Type returnType = typeof(Expression<>).MakeGenericType(typeof(Func<>).MakeGenericType(expressionDescriptor.ResultType));
            string expressionText = null;
            if (IsVB)
            {
                expressionText = string.Concat(vbLambdaString, coreExpressionText);
            }
            else if (IsCS)
            {
                expressionText = string.Concat(csharpLambdaString, coreExpressionText);
            }
 
            if (expressionText != null)
            {
                CodeVariableDeclarationStatement statement = new CodeVariableDeclarationStatement(returnType, "expression", new CodeSnippetExpression(expressionText));
                statement.LinePragma = pragma;
                expressionMethod.Statements.Add(statement);
 
                CodeMethodInvokeExpression invokeExpression = new CodeMethodInvokeExpression(
                    new CodeBaseReferenceExpression(),
                    "RewriteExpressionTree",
                    new CodeExpression[] { new CodeVariableReferenceExpression("expression") });
 
                expressionMethod.Statements.Add(new CodeMethodReturnStatement(invokeExpression));
            }
            else
            {
                expressionMethod.Statements.Add(new CodeMethodReturnStatement(new CodePrimitiveExpression(null)));
            }            
 
            if (isValue)
            {
                dataContextDescriptor.CodeTypeDeclarationForReadOnly.Members.Add(expressionMethod);
            }
            else
            {
                dataContextDescriptor.CodeTypeDeclaration.Members.Add(expressionMethod);
            }            
        }
 
        CodeMemberMethod GenerateGetMethod(Activity activity, Type resultType, string expressionText, int nextExpressionId)
        {
            CodeMemberMethod expressionMethod = new CodeMemberMethod();
            expressionMethod.Attributes = MemberAttributes.Public | MemberAttributes.Final;
            expressionMethod.Name = string.Format(CultureInfo.InvariantCulture, expressionGetString, nextExpressionId);
            expressionMethod.ReturnType = new CodeTypeReference(resultType);
            expressionMethod.CustomAttributes.Add(new CodeAttributeDeclaration(new CodeTypeReference(typeof(DebuggerHiddenAttribute))));
 
            CodeLinePragma pragma;
            AlignText(activity, ref expressionText, out pragma);
            CodeStatement statement = new CodeMethodReturnStatement(new CodeSnippetExpression(expressionText));
            statement.LinePragma = pragma;
            expressionMethod.Statements.Add(statement);
 
            return expressionMethod;
        }
 
        CodeMemberMethod GenerateGetMethodWrapper(CodeMemberMethod expressionMethod)
        {
            CodeMemberMethod wrapperMethod = new CodeMemberMethod();
            wrapperMethod.Attributes = MemberAttributes.Public | MemberAttributes.Final;
            wrapperMethod.Name = valueTypeAccessorString + expressionMethod.Name;
            wrapperMethod.ReturnType = expressionMethod.ReturnType;
 
            wrapperMethod.Statements.Add(new CodeMethodInvokeExpression(
                new CodeMethodReferenceExpression(
                    new CodeThisReferenceExpression(),
                    getValueTypeValuesString)));
 
            wrapperMethod.Statements.Add(new CodeMethodReturnStatement(
                new CodeMethodInvokeExpression(
                    new CodeMethodReferenceExpression(
                        new CodeThisReferenceExpression(),
                        expressionMethod.Name))));
 
            return wrapperMethod;
        }
 
        CodeMemberMethod GenerateSetMethod(Activity activity, Type resultType, string expressionText, int nextExpressionId)
        {
            string paramName = "value";
 
            if (string.Compare(expressionText, paramName, true, Globalization.CultureInfo.CurrentCulture) == 0)
            {
                paramName += "1";
            }
 
            CodeMemberMethod expressionMethod = new CodeMemberMethod();
            expressionMethod.Attributes = MemberAttributes.Public | MemberAttributes.Final;
            expressionMethod.Name = string.Format(CultureInfo.InvariantCulture, expressionSetString, nextExpressionId);
            expressionMethod.CustomAttributes.Add(new CodeAttributeDeclaration(new CodeTypeReference(typeof(DebuggerHiddenAttribute))));
 
            var exprValueParam = new CodeParameterDeclarationExpression(resultType, paramName);
            expressionMethod.Parameters.Add(exprValueParam);
 
            CodeLinePragma pragma;
            AlignText(activity, ref expressionText, out pragma);
            CodeAssignStatement statement = new CodeAssignStatement(new CodeSnippetExpression(expressionText), new CodeArgumentReferenceExpression(paramName));
            statement.LinePragma = pragma;
            expressionMethod.Statements.Add(statement);
            
            return expressionMethod;
        }
 
        CodeMemberMethod GenerateSetMethodWrapper(CodeMemberMethod expressionMethod)
        {
            CodeMemberMethod wrapperMethod = new CodeMemberMethod();
            wrapperMethod.Attributes = MemberAttributes.Public | MemberAttributes.Final;
            wrapperMethod.Name = valueTypeAccessorString + expressionMethod.Name;
 
            CodeParameterDeclarationExpression exprValueParam = new CodeParameterDeclarationExpression(expressionMethod.Parameters[0].Type, expressionMethod.Parameters[0].Name);
            wrapperMethod.Parameters.Add(exprValueParam);
 
            wrapperMethod.Statements.Add(new CodeMethodInvokeExpression(
                new CodeMethodReferenceExpression(
                    new CodeThisReferenceExpression(),
                    getValueTypeValuesString)));
 
            CodeMethodInvokeExpression setExpression = new CodeMethodInvokeExpression(
                new CodeMethodReferenceExpression(
                    new CodeThisReferenceExpression(),
                    expressionMethod.Name));
 
            setExpression.Parameters.Add(new CodeVariableReferenceExpression(expressionMethod.Parameters[0].Name));
 
            wrapperMethod.Statements.Add(setExpression);
 
            wrapperMethod.Statements.Add(new CodeMethodInvokeExpression(
                new CodeMethodReferenceExpression(
                    new CodeThisReferenceExpression(),
                    setValueTypeValuesString)));
 
            return wrapperMethod;
        }
 
        CodeMemberMethod GenerateStatementMethod(Activity activity, string expressionText, int nextExpressionId)
        {
            CodeMemberMethod expressionMethod = new CodeMemberMethod();
            expressionMethod.Attributes = MemberAttributes.Public | MemberAttributes.Final;
            expressionMethod.Name = string.Format(CultureInfo.InvariantCulture, expressionStatementString, nextExpressionId);
            expressionMethod.CustomAttributes.Add(new CodeAttributeDeclaration(new CodeTypeReference(typeof(DebuggerHiddenAttribute))));
 
            CodeLinePragma pragma;
            AlignText(activity, ref expressionText, out pragma);
            CodeStatement statement = new CodeSnippetStatement(expressionText);
            statement.LinePragma = pragma;
            expressionMethod.Statements.Add(statement);
 
            return expressionMethod;
        }
 
        CodeMemberMethod GenerateStatementMethodWrapper(CodeMemberMethod expressionMethod)
        {
            CodeMemberMethod wrapperMethod = new CodeMemberMethod();
            wrapperMethod.Attributes = MemberAttributes.Public | MemberAttributes.Final;
            wrapperMethod.Name = valueTypeAccessorString + expressionMethod.Name;
 
            wrapperMethod.Statements.Add(new CodeMethodInvokeExpression(
                new CodeMethodReferenceExpression(
                    new CodeThisReferenceExpression(),
                    getValueTypeValuesString)));
 
            CodeMethodInvokeExpression setExpression = new CodeMethodInvokeExpression(
                new CodeMethodReferenceExpression(
                    new CodeThisReferenceExpression(),
                    expressionMethod.Name));
 
            wrapperMethod.Statements.Add(setExpression);
 
            wrapperMethod.Statements.Add(new CodeMethodInvokeExpression(
                new CodeMethodReferenceExpression(
                    new CodeThisReferenceExpression(),
                    setValueTypeValuesString)));
 
            return wrapperMethod;
        }
        
        CodeMemberMethod GenerateGetValueTypeValues(CompiledDataContextDescriptor descriptor)
        {
            CodeMemberMethod fetchMethod = new CodeMemberMethod();
            fetchMethod.Name = getValueTypeValuesString;
            fetchMethod.Attributes = MemberAttributes.Override | MemberAttributes.Family;
            
            foreach (KeyValuePair<string, MemberData> valueField in descriptor.Fields)
            {
                if (descriptor.Duplicates.Contains(valueField.Key))
                {
                    continue;
                }
                
                CodeExpression getValue = new CodeCastExpression(
                    valueField.Value.Type,
                    new CodeMethodInvokeExpression(
                        new CodeMethodReferenceExpression(
                            new CodeThisReferenceExpression(), 
                            "GetVariableValue"), 
                             new CodeBinaryOperatorExpression(
                                 new CodePrimitiveExpression(valueField.Value.Index), 
                                 CodeBinaryOperatorType.Add,
                                 new CodeVariableReferenceExpression("locationsOffset"))));
 
                CodeFieldReferenceExpression fieldReference = new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), valueField.Key);
 
                fetchMethod.Statements.Add(
                    new CodeAssignStatement(fieldReference, getValue));
            }
 
            fetchMethod.Statements.Add(new CodeMethodInvokeExpression(
                new CodeMethodReferenceExpression(
                    new CodeBaseReferenceExpression(),
                    fetchMethod.Name)));
            
            return fetchMethod;
        }
 
        CodeMemberMethod GenerateSetValueTypeValues(CompiledDataContextDescriptor descriptor)
        {
            CodeMemberMethod pushMethod = new CodeMemberMethod();
            pushMethod.Name = setValueTypeValuesString;
            pushMethod.Attributes = MemberAttributes.Override | MemberAttributes.Family;
 
            foreach (KeyValuePair<string, MemberData> valueField in descriptor.Fields)
            {
                if (descriptor.Duplicates.Contains(valueField.Key))
                {
                    continue;
                }
 
                CodeMethodInvokeExpression setValue = new CodeMethodInvokeExpression(
                    new CodeMethodReferenceExpression(
                        new CodeThisReferenceExpression(),
                        "SetVariableValue"),
                        new CodeBinaryOperatorExpression(
                        new CodePrimitiveExpression(valueField.Value.Index),
                        CodeBinaryOperatorType.Add, 
                        new CodeVariableReferenceExpression("locationsOffset")),
                        new CodeFieldReferenceExpression(
                            new CodeThisReferenceExpression(), valueField.Key));
                
                pushMethod.Statements.Add(setValue);
            }
 
            pushMethod.Statements.Add(new CodeMethodInvokeExpression(
                new CodeMethodReferenceExpression(
                    new CodeBaseReferenceExpression(),
                    pushMethod.Name)));
 
            return pushMethod;
        }
 
        CodeTypeDeclaration GenerateCompiledDataContext(bool forReadOnly)
        {
            string forReadOnlyString = forReadOnly ? TextExpressionCompiler.forReadOnly : string.Empty;
            string contextName = string.Concat(this.settings.ActivityName, TextExpressionCompiler.typedDataContextName, this.nextContextId, forReadOnlyString);
 
            CodeTypeDeclaration typedDataContext = new CodeTypeDeclaration(contextName);
            typedDataContext.TypeAttributes = TypeAttributes.NestedPrivate;
            //
            // data context classes are declared inside of the main class via the partial class to reduce visibility/surface area.
            this.classDeclaration.Members.Add(typedDataContext);
 
            if (this.compiledDataContexts != null && this.compiledDataContexts.Count > 0)
            {
                string baseTypeName = null;
                if (forReadOnly)
                {
                    baseTypeName = this.compiledDataContexts.Peek().CodeTypeDeclarationForReadOnly.Name;
                }
                else
                {
                    baseTypeName = this.compiledDataContexts.Peek().CodeTypeDeclaration.Name;
                }
                typedDataContext.BaseTypes.Add(baseTypeName);
            }
            else
            {
                typedDataContext.BaseTypes.Add(typeof(CompiledDataContext));
                //
                // We only generate the helper method on the root data context/context 0
                // No need to have it on all contexts.  This is just a slight of hand
                // so that we don't need to make GetDataContextActivities public on CompiledDataContext.
                typedDataContext.Members.Add(GenerateDataContextActivitiesHelper());
            }
 
            CodeMemberField offsetField = new CodeMemberField();
            offsetField.Attributes = MemberAttributes.Private;
            offsetField.Name = locationsOffsetFieldName;
            offsetField.Type = new CodeTypeReference(typeof(int));
 
            typedDataContext.Members.Add(offsetField);
 
            CodeMemberField expectedLocationsCountField = new CodeMemberField();
            expectedLocationsCountField.Attributes = MemberAttributes.Private | MemberAttributes.Static;
            expectedLocationsCountField.Name = expectedLocationsCountFieldName;
            expectedLocationsCountField.Type = new CodeTypeReference(typeof(int));
 
            typedDataContext.Members.Add(expectedLocationsCountField);
 
            typedDataContext.Members.Add(GenerateLocationReferenceActivityContextConstructor());
            typedDataContext.Members.Add(GenerateLocationConstructor());
            typedDataContext.Members.Add(GenerateLocationReferenceConstructor());
            typedDataContext.Members.Add(GenerateCacheHelper());
            typedDataContext.Members.Add(GenerateSetLocationsOffsetMethod());
 
            //
            // Mark this type as tool generated code
            typedDataContext.CustomAttributes.Add(GeneratedCodeAttribute);
            //
            // Mark it as Browsable(false) 
            // Note that this does not prevent intellisense within a single project, just at the metadata level            
            typedDataContext.CustomAttributes.Add(BrowsableCodeAttribute);
            //
            // Mark it as EditorBrowsable(EditorBrowsableState.Never)
            // Note that this does not prevent intellisense within a single project, just at the metadata level
            typedDataContext.CustomAttributes.Add(EditorBrowsableCodeAttribute);
 
            return typedDataContext;
        }
 
        CodeMemberMethod GenerateDataContextActivitiesHelper()
        {
            CodeMemberMethod dataContextActivitiesHelper = new CodeMemberMethod();
 
            dataContextActivitiesHelper.Name = "GetDataContextActivitiesHelper";
 
            dataContextActivitiesHelper.Attributes = MemberAttributes.Assembly | MemberAttributes.Final | MemberAttributes.Static;
 
            if (this.compiledDataContexts != null && this.compiledDataContexts.Count > 0)
            {
                dataContextActivitiesHelper.Attributes |= MemberAttributes.New;
            }
 
            dataContextActivitiesHelper.ReturnType = new CodeTypeReference(typeof(object));
 
            dataContextActivitiesHelper.Parameters.Add(
                new CodeParameterDeclarationExpression(
                    new CodeTypeReference(typeof(Activity)),
                    "compiledRoot"));
 
            dataContextActivitiesHelper.Parameters.Add(
                new CodeParameterDeclarationExpression(
                    new CodeTypeReference(typeof(bool)),
                    forImplementationName));
 
            dataContextActivitiesHelper.Statements.Add(
                new CodeMethodReturnStatement(
                    new CodeMethodInvokeExpression(
                        new CodeMethodReferenceExpression(
                            new CodeTypeReferenceExpression(typeof(CompiledDataContext)),
                            "GetDataContextActivities"),
                        new CodeVariableReferenceExpression("compiledRoot"),
                        new CodeVariableReferenceExpression(forImplementationName))));
 
            return dataContextActivitiesHelper;
        }
 
        CodeMemberMethod GenerateSetLocationsOffsetMethod()
        {
            CodeMemberMethod setLocationsOffsetMethod = new CodeMemberMethod();
            setLocationsOffsetMethod.Name = "SetLocationsOffset";
            setLocationsOffsetMethod.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference(typeof(int)),
                    "locationsOffsetValue"));
            setLocationsOffsetMethod.Attributes = MemberAttributes.Public;
            if (this.compiledDataContexts.Count > 0)
            {
                setLocationsOffsetMethod.Attributes |= MemberAttributes.New;
            }
 
            CodeAssignStatement assignLocationsOffsetStatement = new CodeAssignStatement(
                new CodeVariableReferenceExpression("locationsOffset"),
                new CodeVariableReferenceExpression("locationsOffsetValue"));
            setLocationsOffsetMethod.Statements.Add(assignLocationsOffsetStatement);
 
            if (this.nextContextId > 0)
            {
                CodeMethodInvokeExpression baseSetLocationsOffsetMethod = new CodeMethodInvokeExpression(
                    new CodeBaseReferenceExpression(), "SetLocationsOffset", new CodeVariableReferenceExpression("locationsOffset"));
                setLocationsOffsetMethod.Statements.Add(baseSetLocationsOffsetMethod);
            }
 
            return setLocationsOffsetMethod;
        }
 
        CodeMemberMethod GenerateCacheHelper()
        {
            CodeMemberMethod cacheHelper = new CodeMemberMethod();
            cacheHelper.Name = "GetCompiledDataContextCacheHelper";
            cacheHelper.Attributes = MemberAttributes.Assembly | MemberAttributes.Final | MemberAttributes.Static;
 
            if (this.compiledDataContexts != null && this.compiledDataContexts.Count > 0)
            {
                cacheHelper.Attributes |= MemberAttributes.New;
            }
 
            cacheHelper.Parameters.Add(new CodeParameterDeclarationExpression(typeof(object), dataContextActivitiesFieldName));
            cacheHelper.Parameters.Add(new CodeParameterDeclarationExpression(typeof(ActivityContext), "activityContext"));
            cacheHelper.Parameters.Add(new CodeParameterDeclarationExpression(typeof(Activity), "compiledRoot"));
            cacheHelper.Parameters.Add(new CodeParameterDeclarationExpression(typeof(bool), forImplementationName));
            cacheHelper.Parameters.Add(new CodeParameterDeclarationExpression(typeof(int), "compiledDataContextCount"));
 
            cacheHelper.ReturnType = new CodeTypeReference(typeof(CompiledDataContext[]));
 
            cacheHelper.Statements.Add(
                new CodeMethodReturnStatement(
                    new CodeMethodInvokeExpression(
                        new CodeMethodReferenceExpression(
                            new CodeTypeReferenceExpression(typeof(CompiledDataContext)),
                            "GetCompiledDataContextCache"),
                        new CodeVariableReferenceExpression(dataContextActivitiesFieldName),
                        new CodeVariableReferenceExpression("activityContext"),
                        new CodeVariableReferenceExpression("compiledRoot"),
                        new CodeVariableReferenceExpression(forImplementationName),
                        new CodeVariableReferenceExpression("compiledDataContextCount"))));
 
            return cacheHelper;
        }
 
        CodeConstructor GenerateLocationReferenceActivityContextConstructor()
        {
            //
            // public [typename](IList<LocationReference> locations, ActivityContext activityContext)
            //   : base(locations, activityContext)
            //
            CodeConstructor constructor = new CodeConstructor();
            constructor.Attributes = MemberAttributes.Public;
 
            CodeParameterDeclarationExpression constructorLocationsParam =
                new CodeParameterDeclarationExpression(typeof(IList<LocationReference>), "locations");
            constructor.Parameters.Add(constructorLocationsParam);
 
            constructor.BaseConstructorArgs.Add(new CodeArgumentReferenceExpression("locations"));
 
            CodeParameterDeclarationExpression constructorActivityContextParam = 
                new CodeParameterDeclarationExpression(typeof(ActivityContext), "activityContext");
            constructor.Parameters.Add(constructorActivityContextParam);
 
            constructor.BaseConstructorArgs.Add(new CodeArgumentReferenceExpression("activityContext"));
 
            CodeParameterDeclarationExpression computelocationsOffsetParam = 
                new CodeParameterDeclarationExpression(typeof(bool), "computelocationsOffset");
            constructor.Parameters.Add(computelocationsOffsetParam);
 
            if (this.nextContextId > 0)
            {
                constructor.BaseConstructorArgs.Add(new CodePrimitiveExpression(false));
            }
 
            InvokeSetLocationsOffsetMethod(constructor);           
            
            return constructor;
        }
 
        CodeConstructor GenerateLocationConstructor()
        {
            //
            // public [typename](IList<Location> locations, ActivityContext activityContext)
            //   : base(locations)
            //
            CodeConstructor constructor = new CodeConstructor();
            constructor.Attributes = MemberAttributes.Public;
 
            CodeParameterDeclarationExpression constructorLocationsParam =
                new CodeParameterDeclarationExpression(typeof(IList<Location>), "locations");
            constructor.Parameters.Add(constructorLocationsParam);
 
            constructor.BaseConstructorArgs.Add(new CodeArgumentReferenceExpression("locations"));
 
            CodeParameterDeclarationExpression computelocationsOffsetParam =
                new CodeParameterDeclarationExpression(typeof(bool), "computelocationsOffset");
            constructor.Parameters.Add(computelocationsOffsetParam);
 
            if (this.nextContextId > 0)
            {                
                constructor.BaseConstructorArgs.Add(new CodePrimitiveExpression(false));
            }
 
            InvokeSetLocationsOffsetMethod(constructor);
   
            return constructor;
        }
 
        CodeConstructor GenerateLocationReferenceConstructor()
        {
            //
            // public [typename](IList<LocationReference> locationReferences)
            //   : base(locationReferences)
            //
            CodeConstructor constructor = new CodeConstructor();
            constructor.Attributes = MemberAttributes.Public;
 
            CodeParameterDeclarationExpression constructorLocationsParam = new CodeParameterDeclarationExpression(typeof(IList<LocationReference>), "locationReferences");
            constructor.Parameters.Add(constructorLocationsParam);
 
            constructor.BaseConstructorArgs.Add(new CodeArgumentReferenceExpression("locationReferences"));
 
            return constructor;
        }
 
        void InvokeSetLocationsOffsetMethod(CodeConstructor constructor)
        {
            CodeExpressionStatement setLocationsOffsetMethod = new CodeExpressionStatement(
                new CodeMethodInvokeExpression(
                new CodeThisReferenceExpression(),
                "SetLocationsOffset",
                new CodeBinaryOperatorExpression(
                    new CodePropertyReferenceExpression(new CodeVariableReferenceExpression("locations"), "Count"),
                    CodeBinaryOperatorType.Subtract,
                    new CodeVariableReferenceExpression("expectedLocationsCount"))));
            
            CodeConditionStatement offsetCheckStatement = new CodeConditionStatement(new CodeBinaryOperatorExpression(
                new CodeVariableReferenceExpression("computelocationsOffset"),
                CodeBinaryOperatorType.ValueEquality,
                new CodePrimitiveExpression(true)),
                new CodeStatement[] { setLocationsOffsetMethod });
            
            constructor.Statements.Add(offsetCheckStatement);            
        }
 
        CodeNamespace GenerateCodeNamespace()
        {
            CodeNamespace codeNamespace = new CodeNamespace(this.settings.ActivityNamespace);            
 
            bool seenXamlIntegration = false;
            foreach (string nsReference in GetNamespaceReferences())
            {
                if (!seenXamlIntegration && nsReference == xamlIntegrationNamespace)
                {
                    seenXamlIntegration = true;
                }
                codeNamespace.Imports.Add(new CodeNamespaceImport(nsReference)
                {
                    LinePragma = GenerateLinePragmaForNamespace(nsReference),
                });
            }
 
            if (!seenXamlIntegration)
            {
                codeNamespace.Imports.Add(new CodeNamespaceImport(xamlIntegrationNamespace)
                {
                    LinePragma = GenerateLinePragmaForNamespace(xamlIntegrationNamespace),
                });
            }
 
            return codeNamespace;
        }
 
        bool AssemblyContainsTypeWithActivityNamespace()
        {
            // We need to include the ActivityNamespace in the imports if there are any types in
            // the Activity's assembly that are contained in that namespace.
            Type[] types;
            try
            {
                types = this.settings.Activity.GetType().Assembly.GetTypes();
            }
            catch (ReflectionTypeLoadException)
            {
                // We had a problem loading all the types. Take the safe route and assume we need to include the ActivityNamespace.
                return true;
            }
 
            if (types != null)
            {
                foreach (Type type in types)
                {
                    if (type.Namespace == this.settings.ActivityNamespace)
                    {
                        return true;
                    }
                }
            }
            return false;
        }
 
        IEnumerable<string> GetNamespaceReferences()
        {
            HashSet<string> nsReferences = new HashSet<string>();
            // Add some namespace imports, use the same base set for C# as for VB, they aren't lang specific
            foreach (string nsReference in TextExpression.DefaultNamespaces)
            {
                nsReferences.Add(nsReference);
            }
 
 
            VisualBasicSettings vbSettings = null;
            if (IsVB)
            {
                vbSettings = VisualBasic.GetSettings(this.settings.Activity);
            }
            if (vbSettings != null)
            {
                foreach (VisualBasicImportReference nsReference in vbSettings.ImportReferences)
                {
                    if (!string.IsNullOrWhiteSpace(nsReference.Import))
                    {
                        // For VB, the ActivityNamespace has the RootNamespace stripped off. We don't need an Imports reference
                        // to ActivityNamespace, if this reference is in the same assembly and there is a RootNamespace specified.
                        // We check both Assembly.FullName and
                        // Assembly.GetName().Name because testing has shown that nsReference.Assembly sometimes gives fully qualified
                        // names and sometimes not.
                        if (
                            (nsReference.Import == this.settings.ActivityNamespace)
                            &&
                            ((nsReference.Assembly == this.settings.Activity.GetType().Assembly.FullName) ||
                             (nsReference.Assembly == this.settings.Activity.GetType().Assembly.GetName().Name))
                            &&
                            !string.IsNullOrWhiteSpace(this.settings.RootNamespace)
                            &&
                            !AssemblyContainsTypeWithActivityNamespace()
                            )
                        {
                            continue;
                        }
 
                        nsReferences.Add(nsReference.Import);
                    }
                }
            }
            else
            {
                IList<string> references = this.settings.ForImplementation ?
                    TextExpression.GetNamespacesForImplementation(this.settings.Activity) :
                    TextExpression.GetNamespaces(this.settings.Activity);
 
                foreach (string nsReference in references)
                {
                    if (!string.IsNullOrWhiteSpace(nsReference))
                    {
                        nsReferences.Add(nsReference);
                    }
                }
            }
 
            return nsReferences;
        }
 
        CompiledDataContextDescriptor PushDataContextDescriptor()
        {
            CompiledDataContextDescriptor contextDescriptor = new CompiledDataContextDescriptor(() => this.IsVB)
            {
                CodeTypeDeclaration = GenerateCompiledDataContext(false),
                CodeTypeDeclarationForReadOnly = GenerateCompiledDataContext(true),
                NextMemberIndex = GetStartMemberIndex()
            };
            this.compiledDataContexts.Push(contextDescriptor);
            this.nextContextId++;
            
            return contextDescriptor;
        }
 
        void PopDataContextDescriptor()
        {
            CompiledDataContextDescriptor descriptor = this.compiledDataContexts.Pop();
            if (descriptor != null)
            {
                GenerateMembers(descriptor);
                GenerateValidate(descriptor, true);
                GenerateValidate(descriptor, false);
            }
        }
 
        int GetStartMemberIndex()
        {
            if (this.compiledDataContexts == null || this.compiledDataContexts.Count == 0)
            {
                return 0;
            }
            else
            {
                return this.compiledDataContexts.Peek().NextMemberIndex;
            }
        }
                
        void GenerateValidate(CompiledDataContextDescriptor descriptor, bool forReadOnly)
        {
            //
            //
            // Validate the locations at runtime match the set at compile time
            //
            // protected override bool Validate(IList<LocationReference> locationReferences)
            // {
            //   if (validateLocationCount && locationReferences.Count != [generated count of location references])
            //   {
            //     return false;
            //   }
            //   if (locationReferences[0].Name != [generated name for index] ||
            //       locationReferences[0].Type != typeof([generated type for index]))
            //   {
            //     return false;
            //   }
            //
            //   ...
            //
            // }
            CodeMemberMethod validateMethod = new CodeMemberMethod();
            validateMethod.Name = "Validate";
            validateMethod.Attributes = MemberAttributes.Public | MemberAttributes.Static;
 
            if (this.compiledDataContexts.Count > 0)
            {
                validateMethod.Attributes |= MemberAttributes.New;
            }
 
 
            validateMethod.ReturnType = new CodeTypeReference(typeof(bool));
 
            validateMethod.Parameters.Add(
                new CodeParameterDeclarationExpression(
                    new CodeTypeReference(typeof(IList<LocationReference>)),
                    "locationReferences"));
 
            validateMethod.Parameters.Add(
                new CodeParameterDeclarationExpression(
                    new CodeTypeReference(typeof(bool)),
                    "validateLocationCount"));
 
            validateMethod.Parameters.Add(
               new CodeParameterDeclarationExpression(
                   new CodeTypeReference(typeof(int)),
                   "offset") );
 
            CodeBinaryOperatorExpression shouldCheckLocationCountExpression = new CodeBinaryOperatorExpression(
                new CodeVariableReferenceExpression("validateLocationCount"),
                CodeBinaryOperatorType.ValueEquality,
                new CodePrimitiveExpression(true));
 
            CodeBinaryOperatorExpression compareLocationCountExpression = new CodeBinaryOperatorExpression(
                    new CodePropertyReferenceExpression(
                    new CodeVariableReferenceExpression("locationReferences"),            
                    "Count"),
                    CodeBinaryOperatorType.LessThan,
                    new CodePrimitiveExpression(descriptor.NextMemberIndex)
                    );
 
            CodeBinaryOperatorExpression checkLocationCountExpression = new CodeBinaryOperatorExpression(
                shouldCheckLocationCountExpression,
                CodeBinaryOperatorType.BooleanAnd,
                compareLocationCountExpression);
 
            CodeConditionStatement checkLocationCountStatement = new CodeConditionStatement(
                checkLocationCountExpression,
                new CodeMethodReturnStatement(
                    new CodePrimitiveExpression(false)));
 
            validateMethod.Statements.Add(checkLocationCountStatement);
 
            if (descriptor.NextMemberIndex > 0)
            {
                CodeConditionStatement generateNewOffset = new CodeConditionStatement(shouldCheckLocationCountExpression,
                    new CodeStatement[] 
                {
                    new CodeAssignStatement(new CodeVariableReferenceExpression("offset"), 
                    new CodeBinaryOperatorExpression(
                        new CodePropertyReferenceExpression(new CodeVariableReferenceExpression("locationReferences"), "Count"),
                        CodeBinaryOperatorType.Subtract,
                        new CodePrimitiveExpression(descriptor.NextMemberIndex)))
                });
                validateMethod.Statements.Add(generateNewOffset);
            }
 
            CodeAssignStatement setexpectedLocationsCountStatement = new CodeAssignStatement(
                new CodeVariableReferenceExpression("expectedLocationsCount"),
                new CodePrimitiveExpression(descriptor.NextMemberIndex));
 
            validateMethod.Statements.Add(setexpectedLocationsCountStatement);
 
            foreach (KeyValuePair<string, MemberData> kvp in descriptor.Properties)
            {
                validateMethod.Statements.Add(GenerateLocationReferenceCheck(kvp.Value));
            }
 
            foreach (KeyValuePair<string, MemberData> kvp in descriptor.Fields)
            {
                validateMethod.Statements.Add(GenerateLocationReferenceCheck(kvp.Value));
            }
                        
            if (this.compiledDataContexts.Count >= 1)
            {
                CompiledDataContextDescriptor baseDescriptor = this.compiledDataContexts.Peek();
                CodeTypeDeclaration baseType = forReadOnly ? baseDescriptor.CodeTypeDeclarationForReadOnly : baseDescriptor.CodeTypeDeclaration;
 
                CodeMethodInvokeExpression invokeBase = new CodeMethodInvokeExpression(
                    new CodeMethodReferenceExpression(
                        new CodeTypeReferenceExpression(baseType.Name),
                        "Validate"),
                    new CodeVariableReferenceExpression("locationReferences"),
                    new CodePrimitiveExpression(false),
                    new CodeVariableReferenceExpression("offset"));
 
                validateMethod.Statements.Add(
                    new CodeMethodReturnStatement(invokeBase));
            }
            else
            {
                validateMethod.Statements.Add(
                    new CodeMethodReturnStatement(
                        new CodePrimitiveExpression(true)));
            }
 
            if (forReadOnly)
            {
                descriptor.CodeTypeDeclarationForReadOnly.Members.Add(validateMethod);
            }
            else
            {
                descriptor.CodeTypeDeclaration.Members.Add(validateMethod);
            }
        }
 
        CodeConditionStatement GenerateLocationReferenceCheck(MemberData memberData)
        {
            CodeIndexerExpression indexer = new CodeIndexerExpression(
                new CodeVariableReferenceExpression("locationReferences"),
                new CodeBinaryOperatorExpression(new CodeVariableReferenceExpression("offset"),
                    CodeBinaryOperatorType.Add,
                    new CodePrimitiveExpression(memberData.Index)));
 
            CodeBinaryOperatorExpression locationNameExpression = new CodeBinaryOperatorExpression(
                new CodePropertyReferenceExpression(indexer, "Name"),
                CodeBinaryOperatorType.IdentityInequality,
                new CodePrimitiveExpression(memberData.Name));
 
            CodeBinaryOperatorExpression locationTypeExpression = new CodeBinaryOperatorExpression(
                new CodePropertyReferenceExpression(indexer, "Type"),
                CodeBinaryOperatorType.IdentityInequality,
                new CodeTypeOfExpression(memberData.Type));
 
            CodeBinaryOperatorExpression locationExpression = new CodeBinaryOperatorExpression(
                locationNameExpression,
                CodeBinaryOperatorType.BooleanOr,
                locationTypeExpression);
            
            CodeMethodReturnStatement returnStatement = new CodeMethodReturnStatement();
 
            returnStatement.Expression = new CodePrimitiveExpression(false);
 
            CodeConditionStatement locationStatement = new CodeConditionStatement(
                locationExpression,
                returnStatement);
 
            return locationStatement;
        }
        
        [Fx.Tag.SecurityNote(Critical = "Critical because we are accessing CodeDom.",
            Safe = "Safe because we are demanding FullTrust")]
        [SecuritySafeCritical]
        [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
        void WriteCode(TextWriter textWriter)
        {
            using (CodeDomProvider codeDomProvider = CodeDomProvider.CreateProvider(this.settings.Language))
            {
                using (IndentedTextWriter indentedTextWriter = new IndentedTextWriter(textWriter))
                {
                    codeDomProvider.GenerateCodeFromNamespace(this.codeNamespace, indentedTextWriter, new CodeGeneratorOptions());
                }
            }
        }
 
        [Fx.Tag.SecurityNote(Critical = "Critical because we are using the CodeDomProvider class, which has a link demand for Full Trust.",
            Safe = "Safe because we are demanding FullTrust")]
        [SecuritySafeCritical]
        [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
        TextExpressionCompilerResults CompileInMemory()
        {
            List<TextExpressionCompilerError> messages = new List<TextExpressionCompilerError>();
            CompilerParameters compilerParameters = GetCompilerParameters(messages);
            
            CompilerResults compilerResults = null;
            using (CodeDomProvider codeDomProvider = CodeDomProvider.CreateProvider(this.settings.Language))
            {
                compilerResults = codeDomProvider.CompileAssemblyFromDom(compilerParameters, this.compileUnit);
            }
 
            TextExpressionCompilerResults results = new TextExpressionCompilerResults();
 
            if (compilerResults.Errors == null || !compilerResults.Errors.HasErrors)
            {
                results.ResultType = compilerResults.CompiledAssembly.GetType(this.activityFullName);
            }
 
            results.HasSourceInfo = this.symbols != null;
 
            bool hasErrors = false;
            if (compilerResults.Errors != null && (compilerResults.Errors.HasWarnings || compilerResults.Errors.HasErrors))
            {
 
                foreach (CompilerError ce in compilerResults.Errors)
                {
                    TextExpressionCompilerError message = new TextExpressionCompilerError();
 
                    message.Message = ce.ErrorText;
                    message.Number = ce.ErrorNumber;
 
                    if (results.HasSourceInfo)
                    {
                        message.SourceLineNumber = ce.Line;
                    }
                    else
                    {
                        message.SourceLineNumber = -1;
                    }
 
                    message.IsWarning = ce.IsWarning;
 
                    messages.Add(message);
 
                    hasErrors |= !message.IsWarning;
                }
            }
 
            if (messages != null && messages.Count > 0)
            {
                results.SetMessages(messages, hasErrors);
            }
 
            return results;
        }
 
        [Fx.Tag.SecurityNote(Critical = "Critical because we are using the CompilerParameters class, which has a link demand for Full Trust.",
            Safe = "Safe because we are demanding FullTrust")]
        [SecuritySafeCritical]
        [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
        CompilerParameters GetCompilerParameters(IList<TextExpressionCompilerError> messages)
        {
            CompilerParameters compilerParameters = new CompilerParameters();
            compilerParameters.GenerateExecutable = false;
            compilerParameters.GenerateInMemory = false;
 
            if (this.IsVB && !string.IsNullOrWhiteSpace(this.settings.RootNamespace))
            {
                compilerParameters.CompilerOptions = string.Concat("/rootnamespace:", this.settings.RootNamespace);
            }
 
            List<AssemblyReference> assemblies = this.settings.ForImplementation ?
                new List<AssemblyReference>(TextExpression.GetReferencesForImplementation(this.settings.Activity)) :
                new List<AssemblyReference>(TextExpression.GetReferences(this.settings.Activity));
 
            assemblies.AddRange(TextExpression.DefaultReferences);
 
            foreach (AssemblyReference assemblyReference in assemblies)
            {
                if (assemblyReference == null)
                {
                    continue;
                }
 
                assemblyReference.LoadAssembly();
 
                if (assemblyReference.Assembly == null)
                {
                    TextExpressionCompilerError warning = new TextExpressionCompilerError();
                    warning.IsWarning = true;
                    warning.Message = SR.TextExpressionCompilerUnableToLoadAssembly(assemblyReference.AssemblyName);
 
                    messages.Add(warning);
 
                    continue;
                }
 
                if (assemblyReference.Assembly.CodeBase == null)
                {
                    TextExpressionCompilerError warning = new TextExpressionCompilerError();
                    warning.IsWarning = true;
                    warning.Message = SR.TextExpressionCompilerNoCodebase(assemblyReference.AssemblyName);
 
                    messages.Add(warning);
 
                    continue;
                }
 
                string fileName = new Uri(assemblyReference.Assembly.CodeBase).LocalPath;
                compilerParameters.ReferencedAssemblies.Add(fileName);
            }
 
            return compilerParameters;
        }
        
        void AlignText(Activity activity, ref string expressionText, out CodeLinePragma pragma)
        {
            pragma = null;
            if (this.symbols != null)
            {
                SourceLocation sourceLocation = null;
 
                Activity currentActivity = activity;
                while (currentActivity != null && !symbols.TryGetValue(currentActivity, out sourceLocation))
                {
                    currentActivity = currentActivity.Parent;
                }
 
                if (sourceLocation != null && !string.IsNullOrWhiteSpace(sourceLocation.FileName))
                {
                    int startLine = sourceLocation.StartLine;
                    if (startLine > 1)
                    {
                        bool aligned = TryAlign(sourceLocation.StartColumn, ref expressionText);
                        if (aligned)
                        {
                            // Alignment inserts an extra blank line at the beginning of the expression
                            startLine--;
                        }
                    }
 
                    pragma = new CodeLinePragma(sourceLocation.FileName, startLine);
                }
            }
        }
 
        bool TryAlign(int alignment, ref string expressionText)
        {
            if (!this.IsVB && !this.IsCS)
            {
                return false;
            }
 
            StringBuilder builder = new StringBuilder();
            if (this.IsVB)
            {
                builder.Append('_');
            }
            builder.Append(Environment.NewLine);
            builder.Append(new string(' ', alignment - 1));
            builder.Append(expressionText);
            expressionText = builder.ToString();
            return true;
        }
 
        CodeLinePragma GenerateLinePragmaForNamespace(string namespaceName)
        {
            if (this.fileName != null)
            {
                // if source xaml file doesn't exist or it doesn't contain TextExpression
                // it defaults to line number 1
                int lineNumber = 1;
                Dictionary<string, int> lineNumberDictionary = this.settings.ForImplementation ? this.lineNumbersForNSesForImpl : this.lineNumbersForNSes;
 
                int lineNumReturend;
                if (lineNumberDictionary.TryGetValue(namespaceName, out lineNumReturend))
                {
                    lineNumber = lineNumReturend;
                }
 
                return new CodeLinePragma(this.fileName, lineNumber);
            }
            return null;
        }
 
        bool TryGetSymbols(Activity rootActivity, out Dictionary<object, SourceLocation> symbols, out string fileName)
        {
            symbols = null;
            fileName = null;
            Activity implementationRoot = null;
            if (this.settings.ForImplementation)
            {
                // Regular compilation case via XamlBuildTask or for DynamicActivity  
                // Debugger Symbols are attached to the first implementation child of rootActivity
                IEnumerable<Activity> children = WorkflowInspectionServices.GetActivities(rootActivity);
                foreach (Activity child in children)
                {
                    // Find the first implementation child of an activity
                    if (child.Id.Contains("."))
                    {
                        implementationRoot = child;
                        break;
                    }
                }
            }
            else
            {
                // XamlX case
                // Debugger Symbols are attached to WorkflowService.Body which is passed in the rootActivity
                implementationRoot = rootActivity;
            }
 
            if (implementationRoot == null)
            {
                return false;
            }
 
            try
            {
                string symbolString = DebugSymbol.GetSymbol(implementationRoot) as string;
                if (!string.IsNullOrEmpty(symbolString))
                {
                    WorkflowSymbol wfSymbol = WorkflowSymbol.Decode(symbolString);
                    if (wfSymbol != null)
                    {
                        symbols = SourceLocationProvider.GetSourceLocations(rootActivity, wfSymbol);
                        fileName = wfSymbol.FileName;
                        return true;
                    }
                }
            }
            catch (Exception e)
            {
                if (Fx.IsFatal(e))
                {
                    throw;
                }
                // Ignore invalid symbols.
            }
 
            return false;
        }
 
        string GetActivityFullName(TextExpressionCompilerSettings settings)
        {
            string rootNamespacePrefix = null;
            string namespacePrefix = null;
            string activityFullName = "";
            if (this.IsVB && !String.IsNullOrWhiteSpace(this.settings.RootNamespace))
            {
                rootNamespacePrefix = this.settings.RootNamespace + ".";
            }
 
            if (!String.IsNullOrWhiteSpace(this.settings.ActivityNamespace))
            {
                namespacePrefix = this.settings.ActivityNamespace + ".";
            }
 
            if (rootNamespacePrefix != null)
            {
                if (namespacePrefix != null)
                {
                    activityFullName = rootNamespacePrefix + namespacePrefix + settings.ActivityName;
                }
                else
                {
                    activityFullName = rootNamespacePrefix + settings.ActivityName;
                }
            }
            else
            {
                if (namespacePrefix != null)
                {
                    activityFullName = namespacePrefix + settings.ActivityName;
                }
                else
                {
                    activityFullName = settings.ActivityName;
                }
            }
 
            return activityFullName;
        }
 
        class ExpressionCompilerActivityVisitor : CompiledExpressionActivityVisitor
        {
            TextExpressionCompiler compiler;
 
            public ExpressionCompilerActivityVisitor(TextExpressionCompiler compiler)
            {
                this.compiler = compiler;
            }
 
            public int NextExpressionId
            {
                get;
                set;
            }
 
            protected override void Visit(Activity activity, out bool exit)
            {
                base.Visit(activity, out exit);
            }
 
            protected override void VisitRoot(Activity activity, out bool exit)
            {
                this.compiler.OnRootActivity();
                                
                base.VisitRoot(activity, out exit);
                
                this.compiler.OnAfterRootActivity();
            }
 
            protected override void VisitRootImplementationArguments(Activity activity, out bool exit)
            {
                base.VisitRootImplementationArguments(activity, out exit);
 
                if (this.ForImplementation)
                {
                    this.compiler.OnAfterRootArguments(activity);
                }
            }
            
            protected override void VisitVariableScope(Activity activity, out bool exit)
            {
                this.compiler.OnVariableScope(activity);
 
                base.VisitVariableScope(activity, out exit);
                this.compiler.OnAfterVariableScope();
            }
 
            protected override void VisitRootImplementationScope(Activity activity, out bool exit)
            {
                CompiledDataContextDescriptor rootArgumentAccessorContext = null;
                this.compiler.OnRootImplementationScope(activity, out rootArgumentAccessorContext);
 
                base.VisitRootImplementationScope(activity, out exit);
 
                this.compiler.OnAfterRootImplementationScope(activity, rootArgumentAccessorContext);
            }
 
            protected override void VisitVariableScopeArgument(RuntimeArgument runtimeArgument, out bool exit)
            {
                this.compiler.InVariableScopeArgument = true;
                base.VisitVariableScopeArgument(runtimeArgument, out exit);
                this.compiler.InVariableScopeArgument = false;
            }
 
            protected override void VisitITextExpression(Activity activity, out bool exit)
            {
                this.compiler.OnITextExpressionFound(activity, this);
                exit = false;
            }
 
            protected override void VisitDelegate(ActivityDelegate activityDelegate, out bool exit)
            {
                this.compiler.OnActivityDelegateScope();
                                
                base.VisitDelegate(activityDelegate, out exit);
 
                this.compiler.OnAfterActivityDelegateScope();
 
                exit = false;
            }
 
            protected override void VisitDelegateArgument(RuntimeDelegateArgument delegateArgument, out bool exit)
            {
                this.compiler.OnDelegateArgument(delegateArgument);
 
                base.VisitDelegateArgument(delegateArgument, out exit);
            }  
        }
 
        class CompiledExpressionDescriptor
        {
            internal bool IsValue
            {
                get
                {
                    return !string.IsNullOrWhiteSpace(this.GetMethodName) &&
                        string.IsNullOrWhiteSpace(this.SetMethodName) &&
                        string.IsNullOrWhiteSpace(this.StatementMethodName);
                }
            }
 
            internal bool IsReference
            {
                get
                {
                    return !string.IsNullOrWhiteSpace(this.SetMethodName);
                }
            }
 
            internal bool IsStatement
            {
                get
                {
                    return !string.IsNullOrWhiteSpace(this.StatementMethodName);
                }
            }
 
            internal string TypeName
            {
                get;
                set;
            }
 
            internal Type ResultType
            {
                get;
                set;
            }
 
            internal string GetMethodName
            {
                get;
                set;
            }
 
            internal string SetMethodName
            {
                get;
                set;
            }
 
            internal string StatementMethodName
            {
                get;
                set;
            }
 
            internal int Id
            {
                get;
                set;
            }
 
            internal string ExpressionText
            {
                get;
                set;
            }
            
            internal string GetExpressionTreeMethodName
            {
                get;
                set;
            }
        }
 
        class CompiledDataContextDescriptor
        {
            IDictionary<string, MemberData> fields;
            IDictionary<string, MemberData> properties;
            ISet<string> duplicates;
            Func<bool> isVb;
 
            public CompiledDataContextDescriptor(Func<bool> isVb)
            {
                this.isVb = isVb;
            }
                        
            public IDictionary<string, MemberData> Fields
            {
                get
                {
                    if (this.fields == null)
                    {
                        if (this.isVb())
                        {
                            this.fields = new Dictionary<string, MemberData>(StringComparer.OrdinalIgnoreCase);
                        }
                        else
                        {
                            this.fields = new Dictionary<string, MemberData>();
                        }
                    }
                    return this.fields;
                }
            }
 
            public IDictionary<string, MemberData> Properties
            {
                get
                {
                    if (this.properties == null)
                    {
                        if (this.isVb())
                        {
                            this.properties = new Dictionary<string, MemberData>(StringComparer.OrdinalIgnoreCase);
                        }
                        else
                        {
                            this.properties = new Dictionary<string, MemberData>();
                        }
                    }
                    return this.properties;
                }
            }
 
            public ISet<string> Duplicates
            {
                get
                {
                    if (this.duplicates == null)
                    {
                        if (this.isVb())
                        {
                            this.duplicates = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
                        }
                        else
                        {
                            this.duplicates = new HashSet<string>();
                        }                            
                    }
                    return this.duplicates;
                }
            }
 
            public CodeTypeDeclaration CodeTypeDeclaration
            {
                get;
                set;
            }
 
            public CodeTypeDeclaration CodeTypeDeclarationForReadOnly
            {
                get;
                set;
            }
 
            public int NextMemberIndex
            {
                get;
                set;
            }
        }
 
        struct MemberData
        {
            public int Index;
            public string Name;
            public Type Type;
        }
    }
}