Esempio n. 1
0
        /// <summary>
        /// Given a targeted binding expression (in the form "foo->bar"), this method extracts the target name, target type, and expression text.
        /// </summary>
        private Boolean GetExpressionTargetInfo(IExpressionCompilerState state, DataSourceWrapperInfo dataSourceWrapperInfo,
                                                XObject source, ref String expText, out String expTarget, out Type expTargetType)
        {
            const string TargetExpressionDelimiter = "->";

            var expOriginal = expText;

            var delimiterIndex = expText.IndexOf(TargetExpressionDelimiter);

            if (delimiterIndex >= 0)
            {
                var expPartTarget = expText.Substring(0, delimiterIndex);
                var expPartText   = expText.Substring(delimiterIndex + TargetExpressionDelimiter.Length);

                var matchCandidates = (from element in dataSourceWrapperInfo.DataSourceDefinition.Definition.Descendants()
                                       where (String)element.Attribute("Name") == expPartTarget
                                       select element).ToList();

                if (matchCandidates.Count == 0)
                {
                    throw new BindingExpressionCompilationErrorException(source, dataSourceWrapperInfo.DataSourceDefinition.DefinitionPath,
                                                                         CompilerStrings.ExpressionTargetIsNotFound.Format(expPartTarget));
                }

                if (matchCandidates.Count > 1)
                {
                    throw new BindingExpressionCompilationErrorException(source, dataSourceWrapperInfo.DataSourceDefinition.DefinitionPath,
                                                                         CompilerStrings.ExpressionTargetIsAmbiguous.Format(expPartTarget));
                }

                var match     = matchCandidates.Single();
                var matchName = match.Name.LocalName;

                expText       = expPartText;
                expTargetType = UvmlTypeAnalysis.GetPlaceholderType(dataSourceWrapperInfo.DataSourceType, matchName);

                if (expTargetType == null && !state.GetKnownType(matchName, out expTargetType))
                {
                    throw new BindingExpressionCompilationErrorException(source, dataSourceWrapperInfo.DataSourceDefinition.DefinitionPath,
                                                                         CompilerStrings.ExpressionTargetIsUnrecognizedType.Format(expOriginal, matchName));
                }

                expTarget = String.Format("__UPF_FindName<{0}>(\"{1}\").", CSharpLanguage.GetCSharpTypeName(expTargetType), expPartTarget);

                return(true);
            }

            expTarget     = default(String);
            expTargetType = dataSourceWrapperInfo.DataSourceType;

            return(false);
        }
        /// <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(IExpressionCompilerState state, DataSourceDefinition dataSourceDefinition,
                                                               Type dataSourceWrappedType, XElement element, List <BindingExpressionInfo> expressions)
        {
            var templateAnnotation = element.Annotation <FrameworkTemplateNameAnnotation>();

            if (templateAnnotation != null)
            {
                return;
            }

            var elementName = element.Name.LocalName;
            var elementType = UvmlTypeAnalysis.GetPlaceholderType(dataSourceWrappedType, elementName);

            if (elementType != null || state.GetKnownType(elementName, out elementType))
            {
                var attrs = Enumerable.Union(
                    element.Attributes().Select(x =>
                                                new { Object = (XObject)x, Name = x.Name.LocalName, Value = x.Value }),
                    element.Elements().Where(x => x.Name.LocalName.StartsWith(elementName + ".")).Select(x =>
                                                                                                         new { Object = (XObject)x, Name = x.Name.LocalName, Value = x.Value }));

                foreach (var attr in attrs)
                {
                    var attrValue = attr.Value;
                    if (!BindingExpressions.IsBindingExpression(attrValue))
                    {
                        continue;
                    }

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

                    var expText = BindingExpressions.GetBindingMemberPathPart(attrValue);
                    var expProp = GetBindablePropertyOnDataSource(dataSourceWrappedType, expText);
                    var expType = expProp?.PropertyType ?? dprop.PropertyType;
                    if (typeof(DataTemplate).IsAssignableFrom(expType))
                    {
                        continue;
                    }

                    expressions.Add(new BindingExpressionInfo(attr.Object, attrValue, expType)
                    {
                        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) || defaultProperty == null)
                            {
                                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));
                            }

                            var expText = BindingExpressions.GetBindingMemberPathPart(elementValue);
                            var expProp = GetBindablePropertyOnDataSource(dataSourceWrappedType, expText);

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

            var children = element.Elements();

            foreach (var child in children)
            {
                FindBindingExpressionsInDataSource(state, dataSourceDefinition,
                                                   dataSourceWrappedType, child, expressions);
            }
        }