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