/// <summary>
        /// Writes the source code for the specified data source wrapper.
        /// </summary>
        /// <param name="state">The expression compiler's current state.</param>
        /// <param name="dataSourceWrapperInfo">The <see cref="DataSourceWrapperInfo"/> that describes the data source wrapper being generated.</param>
        private static void WriteSourceCodeForDataSourceWrapper(ExpressionCompilerState state, DataSourceWrapperInfo dataSourceWrapperInfo)
        {
            using (var writer = new DataSourceWrapperWriter())
            {
                // Using statements
                var imports = Enumerable.Union(new[] { "System" }, dataSourceWrapperInfo.Imports).Distinct().OrderBy(x => x);
                foreach (var import in imports)
                {
                    writer.WriteLine("using {0};", import);
                }
                writer.WriteLine();

                // Namespace and class declaration
                var @namespace = dataSourceWrapperInfo.DataSourceDefinition.DataSourceWrapperNamespace;
                writer.WriteLine("namespace " + @namespace);
                writer.WriteLine("{");
                writer.WriteLine("#pragma warning disable 1591");
                writer.WriteLine("#pragma warning disable 0184");
                writer.WriteLine("[System.CLSCompliant(false)]");
                writer.WriteLine("[System.CodeDom.Compiler.GeneratedCode(\"UPF Binding Expression Compiler\", \"{0}\")]", FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).FileVersion);
                writer.WriteLine("public sealed partial class {0} : {1}", dataSourceWrapperInfo.DataSourceWrapperName, writer.GetCSharpTypeName(typeof(CompiledDataSourceWrapper)));
                writer.WriteLine("{");

                // Constructors
                writer.WriteLine("#region Constructors");
                writer.WriteConstructor(dataSourceWrapperInfo);
                writer.WriteLine("#endregion");
                writer.WriteLine();

                // IDataSourceWrapper
                writer.WriteLine("#region IDataSourceWrapper");
                writer.WriteIDataSourceWrapperImplementation(dataSourceWrapperInfo);
                writer.WriteLine("#endregion");
                writer.WriteLine();

                // Methods
                writer.WriteLine("#region Methods");
                var methods = dataSourceWrapperInfo.DataSourceType.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
                foreach (var method in methods)
                {
                    if (!NeedsWrapper(method))
                        continue;

                    writer.WriteWrapperMethod(method);
                }
                writer.WriteLine("#endregion");
                writer.WriteLine();

                // Properties
                writer.WriteLine("#region Properties");
                var properties = dataSourceWrapperInfo.DataSourceType.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
                foreach (var property in properties)
                {
                    if (!NeedsWrapper(property))
                        continue;

                    writer.WriteWrapperProperty(property);
                }
                writer.WriteLine("#endregion");
                writer.WriteLine();

                // Fields
                writer.WriteLine("#region Fields");
                var fields = dataSourceWrapperInfo.DataSourceType.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
                foreach (var field in fields)
                {
                    if (!NeedsWrapper(field))
                        continue;

                    writer.WriteWrapperProperty(field);
                }
                writer.WriteLine("#endregion");
                writer.WriteLine();

                // Expressions
                writer.WriteLine("#region Expressions");
                for (int i = 0; i < dataSourceWrapperInfo.Expressions.Count; i++)
                {
                    var expressionInfo = dataSourceWrapperInfo.Expressions[i];
                    writer.WriteExpressionProperty(state, dataSourceWrapperInfo, expressionInfo, i);
                }
                writer.WriteLine("#endregion");

                // Source code generation complete
                writer.WriteLine("}");
                writer.WriteLine("#pragma warning restore 0184");
                writer.WriteLine("#pragma warning restore 1591");
                writer.WriteLine("}");

                dataSourceWrapperInfo.DataSourceWrapperSourceCode = writer.ToString();
            }
        }
        /// <summary>
        /// Writes the source code for an individual data source wrapper class.
        /// </summary>
        private static void WriteSourceCodeForDataSourceWrapperClass(ExpressionCompilerState state,
            DataSourceWrapperInfo dataSourceWrapperInfo, DataSourceWrapperWriter writer)
        {
            // Class declaration
            writer.WriteLine("[System.CLSCompliant(false)]");
            writer.WriteLine("[System.CodeDom.Compiler.GeneratedCode(\"UPF Binding Expression Compiler\", \"{0}\")]", FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).FileVersion);
            writer.WriteLine("public sealed partial class {0} : {1}", dataSourceWrapperInfo.DataSourceWrapperName, writer.GetCSharpTypeName(typeof(CompiledDataSourceWrapper)));
            writer.WriteLine("{");

            // Constructors
            writer.WriteLine("#region Constructors");
            writer.WriteConstructor(dataSourceWrapperInfo);
            writer.WriteLine("#endregion");
            writer.WriteLine();

            // IDataSourceWrapper
            writer.WriteLine("#region IDataSourceWrapper");
            writer.WriteIDataSourceWrapperImplementation(dataSourceWrapperInfo);
            writer.WriteLine("#endregion");
            writer.WriteLine();

            // Methods
            writer.WriteLine("#region Methods");
            var methods = dataSourceWrapperInfo.DataSourceType.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
            foreach (var method in methods)
            {
                if (!NeedsWrapper(method))
                    continue;

                writer.WriteWrapperMethod(method);
            }
            writer.WriteLine("#endregion");
            writer.WriteLine();

            // Properties
            writer.WriteLine("#region Properties");
            var properties = dataSourceWrapperInfo.DataSourceType.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
            foreach (var property in properties)
            {
                if (!NeedsWrapper(property))
                    continue;

                writer.WriteWrapperProperty(property);
            }
            writer.WriteLine("#endregion");
            writer.WriteLine();

            // Fields
            writer.WriteLine("#region Fields");
            var fields = dataSourceWrapperInfo.DataSourceType.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
            foreach (var field in fields)
            {
                if (!NeedsWrapper(field))
                    continue;

                writer.WriteWrapperProperty(field);
            }
            writer.WriteLine("#endregion");
            writer.WriteLine();

            // Expressions
            writer.WriteLine("#region Expressions");
            for (int i = 0; i < dataSourceWrapperInfo.Expressions.Count; i++)
            {
                var expressionInfo = dataSourceWrapperInfo.Expressions[i];
                writer.WriteExpressionProperty(state, dataSourceWrapperInfo, expressionInfo, i);
            }
            writer.WriteLine("#endregion");

            // Class complete
            writer.WriteLine("}");
        }
        /// <summary>
        /// Builds the source code for the CompilerMetadata class and writes it to a file.
        /// </summary>
        /// <returns>The path to the file to which the class was written.</returns>
        private static String WriteCompilerMetadataFile()
        {
            var writer = new DataSourceWrapperWriter();
            var version = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).FileVersion;
            writer.WriteLine("using System;");
            writer.WriteLine();
            writer.WriteLine("namespace " + PresentationFoundationView.DataSourceWrapperNamespaceForViews);
            writer.WriteLine("{");
            writer.WriteLine("#pragma warning disable 1591");
            writer.WriteLine("#pragma warning disable 0184");
            writer.WriteLine("[System.CLSCompliant(false)]");
            writer.WriteLine("[System.CodeDom.Compiler.GeneratedCode(\"UPF Binding Expression Compiler\", \"{0}\")]", version);
            writer.WriteLine("public sealed class CompilerMetadata");
            writer.WriteLine("{");
            writer.WriteLine("public static String Version {{ get {{ return \"{0}\"; }} }}", version);
            writer.WriteLine("}");
            writer.WriteLine("#pragma warning restore 1591");
            writer.WriteLine("#pragma warning restore 0184");
            writer.WriteLine("}");

            var path = Path.Combine(Path.GetTempPath(), "CompilerMetadata.cs");
            File.WriteAllText(path, writer.ToString());

            return path;
        }
        /// <summary>
        /// Writes the source code for the specified data source wrapper.
        /// </summary>
        private static void WriteSourceCodeForDataSourceWrapper(ExpressionCompilerState state, 
            DataSourceWrapperInfo dataSourceWrapperInfo)
        {
            using (var writer = new DataSourceWrapperWriter())
            {
                // Using statements
                var imports = Enumerable.Union(new[] { "System" }, dataSourceWrapperInfo.Imports).Distinct().OrderBy(x => x);
                foreach (var import in imports)
                {
                    writer.WriteLine("using {0};", import);
                }
                writer.WriteLine();

                // Namespace declaration
                var @namespace = dataSourceWrapperInfo.DataSourceDefinition.DataSourceWrapperNamespace;
                writer.WriteLine("namespace " + @namespace);
                writer.WriteLine("{");
                writer.WriteLine("#pragma warning disable 1591");
                writer.WriteLine("#pragma warning disable 0184");

                // Data source wrapper class - main
                WriteSourceCodeForDataSourceWrapperClass(state, dataSourceWrapperInfo, writer);

                // Data source wrapper class - dependent
                foreach (var dependentWrapperInfo in dataSourceWrapperInfo.DependentWrapperInfos)
                    WriteSourceCodeForDataSourceWrapperClass(state, dependentWrapperInfo, writer);

                // Namespace complete
                writer.WriteLine("#pragma warning restore 0184");
                writer.WriteLine("#pragma warning restore 1591");
                writer.WriteLine("}");

                dataSourceWrapperInfo.DataSourceWrapperSourceCode = writer.ToString();
            }
        }