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);
            }            
        }
        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;
        }
        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;
        }
        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;
        }
        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;
            }
        }
        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;
        }