Beispiel #1
0
        /// <summary>
        /// At this point the start element is created and all the constructor params
        /// have been processed.  Now handle the name=value pairs as property sets.
        /// If we have used a regular start element record, then just use regular
        /// properties.
        /// </summary>

        private void WriteProperties(
            ArrayList        xamlNodes,
            ArrayList        list,
            int              listIndex,
            DefAttributeData data)
        {
            if (list != null && listIndex < list.Count)
            {
                ArrayList propertyNamesSoFar = new ArrayList(list.Count/4);

                for (int k = listIndex; k < list.Count; k+=4)
                {
                    // 
                    if (k > (list.Count-3) ||
                        (list[k+1] is String) ||
                        ((Char)list[k+1]) != '=')
                    {
                        ThrowException(SRID.ParserMarkupExtensionNoNameValue, data.Args,
                                       data.LineNumber, data.LinePosition);
                    }


                    // See if this is a duplicate property definition, and throw if it is.

                    string propertyName = list[k] as String;
                    propertyName = propertyName.Trim();

                    if (propertyNamesSoFar.Contains(propertyName))
                    {
                        ThrowException(SRID.ParserDuplicateMarkupExtensionProperty, propertyName, data.LineNumber, data.LinePosition);
                    }
                    propertyNamesSoFar.Add( propertyName );

                    // Fetch the property context

                    int nameIndex = propertyName.IndexOf(':');
                    string localName = (nameIndex < 0) ? propertyName : propertyName.Substring(nameIndex+1);
                    string prefix = (nameIndex < 0) ? String.Empty : propertyName.Substring(0, nameIndex);

                    string attribNamespaceURI = ResolveAttributeNamespaceURI(prefix, localName, data.TargetNamespaceUri);

                    object dynamicObject;
                    string assemblyName;
                    string typeFullName;
                    Type   declaringType;
                    string dynamicObjectName;

                    AttributeContext attributeContext = GetAttributeContext(
                                                            data.TargetType,
                                                            data.TargetNamespaceUri,
                                                            attribNamespaceURI,
                                                            localName,
                                                        out dynamicObject,
                                                        out assemblyName,
                                                        out typeFullName,
                                                        out declaringType,
                                                        out dynamicObjectName);

                    // Handle nested markup extensions by recursing here.  If the
                    // value is not a markup extension, just store it as text for
                    // runtime resolution.
                    string strValue = list[k+2] as String;
                    AttributeData nestedAttrData = IsMarkupExtensionAttribute(
                                                        data.TargetType,
                                                        propertyName,
                                                    ref strValue,
                                                        data.LineNumber,
                                                        data.LinePosition,
                                                        data.Depth,
                                                        dynamicObject);

                    list[k+2] = strValue;
                    if (nestedAttrData != null)
                    {
                        if (nestedAttrData.IsSimple)
                        {
                            CompileProperty(xamlNodes,
                                            propertyName,
                                            nestedAttrData.Args,
                                            data.TargetType,
                                            data.TargetNamespaceUri,    // xmlns of TargetType
                                            nestedAttrData,
                                            nestedAttrData.LineNumber,
                                            nestedAttrData.LinePosition,
                                            nestedAttrData.Depth);
                        }
                        else
                        {
                            // Bug: Need to check validity of property by calling GetAttributeContext here?
                            CompileAttribute(xamlNodes, nestedAttrData);
                        }
                    }
                    else if (!data.IsUnknownExtension)
                    {
                        CompileProperty(xamlNodes,
                                        propertyName,
                                        ((String)list[k+2]),
                                        data.TargetType,
                                        data.TargetNamespaceUri,    // xmlns of TargetType
                                        null,
                                        data.LineNumber,
                                        data.LinePosition,
                                        data.Depth);
                    }
                }
            }
        }
Beispiel #2
0
        /// <summary>
        /// Parse the string representation of a set of def attributes in MarkupExtension
        /// syntax and return a list of xaml nodes that represents those attributes.
        /// </summary>
        internal void CompileDictionaryKey(
            ArrayList   xamlNodes,
            DefAttributeData data)
        {
            ArrayList list = TokenizeAttributes(data.Args, data.LineNumber, data.LinePosition);

            // If the list is empty, or the second item on the list is an equal sign, then
            // we have a simple markup extension that uses the default constructor.  In all
            // other cases we must have at least one constructor parameter.
            xamlNodes.Add(new XamlKeyElementStartNode(
                                  data.LineNumber,
                                  data.LinePosition,
                                  ++data.Depth,
                                  data.TargetAssemblyName,
                                  data.TargetFullName,
                                  data.TargetType,
                                  null));
            xamlNodes.Add(new XamlEndAttributesNode(
                                  data.LineNumber,
                                  data.LinePosition,
                                  data.Depth,
                                  true));
            int listIndex = 0;
            if (list != null &&
                (list.Count == 1 ||
                 (list.Count > 1 && !(list[1] is String) && ((Char)list[1] == ','))))
            {
                // Go through the constructor parameters, writing them out like complex
                // properties
                WriteConstructorParams(xamlNodes, list, data, ref listIndex);
            }

            // Write properties that come after the element constructor parameters
            WriteProperties(xamlNodes, list, listIndex, data);

            // close up
            xamlNodes.Add(new XamlKeyElementEndNode(
                               data.LineNumber,
                               data.LinePosition,
                               data.Depth--));

        }
Beispiel #3
0
        /// <summary>
        /// At this point the start element is written, and we have to process all
        /// the constructor parameters that follow.  Stop when we hit the first
        /// name=value, or when the end of the attributes is reached.
        /// </summary>
        private void WriteConstructorParams(
                ArrayList        xamlNodes,
                ArrayList        list,
                DefAttributeData data,
            ref int              listIndex)
        {
#if PBTCOMPILER
            int numberOfConstructorAttributes = 0;
#endif

            if (list != null && listIndex < list.Count)
            {
                // Mark the start of the constructor parameter section.  Nodes directly
                // under this one are constructor parameters.  Note that we can have
                // element trees under here.
                xamlNodes.Add(new XamlConstructorParametersStartNode(
                                        data.LineNumber,
                                        data.LinePosition,
                                        ++data.Depth));

                for (; listIndex < list.Count; listIndex+=2)
                {
                    if (!(list[listIndex] is String))
                    {
                        ThrowException(SRID.ParserMarkupExtensionBadConstructorParam, data.Args,
                                       data.LineNumber, data.LinePosition);
                    }

                    // If the next item after the current one is '=', then we've hit the
                    // start of named parameters, so stop
                    if (list.Count > (listIndex+1) &&
                        list[listIndex+1] is Char &&
                        (Char)list[listIndex+1] == '=')
                    {
                        break;
                    }

#if PBTCOMPILER
                    numberOfConstructorAttributes++;
#endif

                    // Handle nested markup extensions by recursing here.  If the
                    // value is not a markup extension, just store it as text for
                    // runtime resolution as a constructor parameter.
                    string value = (String)list[listIndex];
                    AttributeData nestedData = IsMarkupExtensionAttribute(data.DeclaringType,
                                                                          string.Empty,
                                                                      ref value,
                                                                          data.LineNumber,
                                                                          data.LinePosition,
                                                                          data.Depth,
                                                                          null);
                    if (nestedData == null)
                    {
                        RemoveEscapes(ref value);

                        xamlNodes.Add(new XamlTextNode(
                                        data.LineNumber,
                                        data.LinePosition,
                                        data.Depth,
                                        value,
                                        null));
                    }
                    else
                    {
                        CompileAttributeCore(xamlNodes, nestedData);
                    }
                }

                // End of constructor parameter section.
                xamlNodes.Add(new XamlConstructorParametersEndNode(
                                    data.LineNumber,
                                    data.LinePosition,
                                    data.Depth--));

#if PBTCOMPILER
                if (data.TargetType != typeof(UnknownMarkupExtension))
                {
                    // For compile mode, check that there is a constructor with the correct
                    // number of arguments.  In xaml load scenarios, the BamlRecordReader
                    // will do this, so don't bother doing it here.  If the target type is
                    // unknown, then we defer this check until it can be resolved.

                    ConstructorInfo[] infos = data.TargetType.GetConstructors(BindingFlags.Public | BindingFlags.Instance);
                    for (int i=0; i<infos.Length; i++)
                    {
                        ConstructorInfo info = infos[i];
                        ParameterInfo[] paramInfos = info.GetParameters();
                        if (paramInfos.Length == numberOfConstructorAttributes)
                        {
                            // Found a constructor with the right number of arguments
                            return;
                        }
                    }

                    // If we get to here, then no matching constructor was found, so complain
                    ThrowException(SRID.ParserBadConstructorParams, data.TargetType.Name,
                                   numberOfConstructorAttributes.ToString(CultureInfo.CurrentCulture),
                                   data.LineNumber, data.LinePosition);
                }

#endif
            }
        }