/// <summary>
        /// Creates a new instance of <see cref="DataSourceWrapperInfo"/> that represents the specified data source wrapper.
        /// </summary>
        /// <param name="state">The expression compiler's current state.</param>
        /// <param name="dataSourceDefinition">The data source definition for which to retrieve data source wrapper info.</param>
        /// <returns>The <see cref="DataSourceWrapperInfo"/> that was created to represent the specified data source.</returns>
        private static DataSourceWrapperInfo GetDataSourceWrapperInfo(ExpressionCompilerState state, DataSourceDefinition dataSourceDefinition)
        {
            var dataSourceWrappedType = dataSourceDefinition.TemplatedControl;
            if (dataSourceWrappedType == null)
            {
                var definedDataSourceTypeAttr = dataSourceDefinition.Definition.Attribute("ViewModelType");
                var definedDataSourceTypeName = (String)definedDataSourceTypeAttr;
                if (definedDataSourceTypeName == null)
                    return null;
                
                var typeNameCommaIx = definedDataSourceTypeName.IndexOf(',');
                if (typeNameCommaIx < 0)
                {
                    throw new BindingExpressionCompilationErrorException(definedDataSourceTypeAttr, dataSourceDefinition.DefinitionPath,
                        CompilerStrings.ViewModelTypeIsNotFullyQualified.Format(definedDataSourceTypeName));
                }
                
                var definedDataSourceType = Type.GetType(definedDataSourceTypeName);
                if (definedDataSourceType == null)
                {
                    throw new BindingExpressionCompilationErrorException(definedDataSourceTypeAttr, dataSourceDefinition.DefinitionPath,
                        PresentationStrings.ViewModelTypeNotFound.Format(definedDataSourceTypeName));
                }

                dataSourceWrappedType = definedDataSourceType;
            }
            
            var dataSourceWrapperName = dataSourceDefinition.DataSourceWrapperName;
            var dataSourceWrapperExpressions = new List<BindingExpressionInfo>();
            foreach (var element in dataSourceDefinition.Definition.Elements())
            {
                FindBindingExpressionsInDataSource(state, 
                    dataSourceDefinition, dataSourceWrappedType, element, dataSourceWrapperExpressions);
            }

            dataSourceWrapperExpressions = CollapseDataSourceExpressions(dataSourceWrapperExpressions);

            var dataSourceReferences = new List<String>();
            var dataSourceImports = new List<String>();

            var xmlRoot = dataSourceDefinition.Definition.Parent;
            var xmlDirectives = xmlRoot.Elements("Directive");
            foreach (var xmlDirective in xmlDirectives)
            {
                var xmlDirectiveType = (String)xmlDirective.Attribute("Type");
                if (String.IsNullOrEmpty(xmlDirectiveType))
                {
                    throw new BindingExpressionCompilationErrorException(xmlDirective, dataSourceDefinition.DefinitionPath, 
                        CompilerStrings.ViewDirectiveMustHaveType);
                }

                var xmlDirectiveTypeName = xmlDirectiveType.ToLowerInvariant();
                var xmlDirectiveValue = xmlDirective.Value.Trim();
                switch (xmlDirectiveTypeName)
                {
                    case "import":
                        {
                            if (String.IsNullOrEmpty(xmlDirectiveValue))
                            {
                                throw new BindingExpressionCompilationErrorException(xmlDirective, dataSourceDefinition.DefinitionPath,
                                    CompilerStrings.ViewDirectiveHasInvalidValue);
                            }
                            dataSourceImports.Add(xmlDirective.Value.Trim());
                        }
                        break;

                    case "reference":
                        {
                            if (String.IsNullOrEmpty(xmlDirectiveValue))
                            {
                                throw new BindingExpressionCompilationErrorException(xmlDirective, dataSourceDefinition.DefinitionPath,
                                    CompilerStrings.ViewDirectiveHasInvalidValue);
                            }
                            dataSourceReferences.Add(xmlDirective.Value.Trim());
                        }
                        break;

                    default:
                        throw new BindingExpressionCompilationErrorException(xmlDirective, dataSourceDefinition.DefinitionPath,
                            CompilerStrings.ViewDirectiveNotRecognized.Format(xmlDirectiveTypeName));
                }
            }

            return new DataSourceWrapperInfo()
            {
                References = dataSourceReferences,
                Imports = dataSourceImports,
                DataSourceDefinition = dataSourceDefinition,
                DataSourceType = dataSourceWrappedType,
                DataSourceWrapperName = dataSourceWrapperName,
                Expressions = dataSourceWrapperExpressions,
            };
        }
        /// <summary>
        /// Searches the specified XML element tree for binding expressions and adds them to the specified collection.
        /// </summary>
        /// <param name="state">The expression compiler's current state.</param>
        /// <param name="dataSourceDefinition">The data source definition for the data source which is being compiled.</param>
        /// <param name="dataSourceWrappedType">The type for which a data source wrapper is being compiled.</param>
        /// <param name="element">The root of the XML element tree to search.</param>
        /// <param name="expressions">The list to populate with any binding expressions that are found.</param>
        private static void FindBindingExpressionsInDataSource(ExpressionCompilerState state, DataSourceDefinition dataSourceDefinition,
            Type dataSourceWrappedType, XElement element, List<BindingExpressionInfo> expressions)
        {
            var elementName = element.Name.LocalName;
            var elementType = GetPlaceholderType(dataSourceWrappedType, elementName);            
            if (elementType != null || state.GetKnownType(elementName, out elementType))
            {
                var attrs = element.Attributes();
                foreach (var attr in attrs)
                {
                    var attrValue = attr.Value;
                    if (!BindingExpressions.IsBindingExpression(attrValue))
                        continue;
                    
                    var dprop = FindDependencyOrAttachedPropertyByName(state, attr.Name.LocalName, elementType);
                    if (dprop == null)
                    {
                        throw new BindingExpressionCompilationErrorException(attr, dataSourceDefinition.DefinitionPath,
                            CompilerStrings.OnlyDependencyPropertiesCanBeBound.Format(attr.Name.LocalName));
                    }

                    expressions.Add(new BindingExpressionInfo(attr, attrValue, dprop.PropertyType) { GenerateGetter = true });
                }

                if (element.Nodes().Count() == 1)
                {
                    var singleChild = element.Nodes().Single();
                    if (singleChild.NodeType == XmlNodeType.Text)
                    {
                        var elementValue = ((XText)singleChild).Value;
                        if (BindingExpressions.IsBindingExpression(elementValue))
                        {
                            String defaultProperty;
                            if (!state.GetElementDefaultProperty(elementType, out defaultProperty))
                            {
                                throw new BindingExpressionCompilationErrorException(singleChild, dataSourceDefinition.DefinitionPath,
                                    CompilerStrings.ElementDoesNotHaveDefaultProperty.Format(elementType.Name));
                            }

                            var dprop = FindDependencyOrAttachedPropertyByName(state, defaultProperty, elementType);
                            if (dprop == null)
                            {
                                throw new BindingExpressionCompilationErrorException(singleChild, dataSourceDefinition.DefinitionPath,
                                    CompilerStrings.OnlyDependencyPropertiesCanBeBound.Format(defaultProperty));
                            }

                            expressions.Add(new BindingExpressionInfo(singleChild, elementValue, dprop.PropertyType) { GenerateGetter = true });
                        }
                    }
                }
            }

            var children = element.Elements();
            foreach (var child in children)
            {
                FindBindingExpressionsInDataSource(state, dataSourceDefinition, 
                    dataSourceWrappedType, child, expressions);
            }
        }
        /// <summary>
        /// Creates a new <see cref="DataSourceWrapperInfo"/> instance which represents a particular framework template.
        /// </summary>
        private static DataSourceWrapperInfo GetDataSourceWrapperInfoForFrameworkTemplate(ExpressionCompilerState state,
            IEnumerable<String> references, IEnumerable<String> imports, DataSourceDefinition definition)
        {
            var dataSourceWrappedTypeAttr = definition.Definition.Attribute("ViewModelType");
            if (dataSourceWrappedTypeAttr == null)
            {
                throw new BindingExpressionCompilationErrorException(definition.Definition, definition.DefinitionPath,
                    PresentationStrings.TemplateMustSpecifyViewModelType);
            }

            var dataSourceWrappedType = Type.GetType(dataSourceWrappedTypeAttr.Value, false);
            if (dataSourceWrappedType == null)
            {
                throw new BindingExpressionCompilationErrorException(dataSourceWrappedTypeAttr, definition.DefinitionPath,
                    PresentationStrings.ViewModelTypeNotFound.Format(dataSourceWrappedTypeAttr.Value));
            }

            var dataSourceDefinition = definition;
            var dataSourceWrapperName = definition.DataSourceWrapperName;

            var expressions = new List<BindingExpressionInfo>();
            foreach (var element in dataSourceDefinition.Definition.Elements())
            {
                FindBindingExpressionsInDataSource(state,
                    dataSourceDefinition, dataSourceWrappedType, element, expressions);
            }
            expressions = CollapseDataSourceExpressions(expressions);

            return new DataSourceWrapperInfo()
            {
                References = references,
                Imports = imports,
                DataSourceDefinition = dataSourceDefinition,
                DataSourceType = dataSourceWrappedType,
                DataSourceWrapperName = dataSourceWrapperName,
                Expressions = expressions
            };
        }