/// <summary> /// Recursive method. Consumes next characters as markup extension definition. /// Resolves type, ctor arguments and properties of markup extension, /// constructs and initializes it, and returns ProvideValue method result. /// </summary> /// <param name="context">Context object passed to ProvideValue method.</param> private Object processMarkupExtensionCore(IMarkupExtensionContext context) { if (consumeChar( ) != '{') { throw new InvalidOperationException("Syntax error: '{{' token expected at 0."); } processWhitespace(false); String markupExtensionName = processQualifiedName( ); if (markupExtensionName.Length == 0) { throw new InvalidOperationException("Syntax error: markup extension name is empty."); } processWhitespace( ); Type type = resolver.Resolve(markupExtensionName); Object obj = null; List <Object> ctorArgs = new List <object>(); for ( ;;) { if (peekNextChar( ) == '{') { // inner markup extension processing // syntax error if ctor arg defined after any property if (obj != null) { throw new InvalidOperationException("Syntax error: constructor argument" + " cannot be after property assignment."); } Object value = processMarkupExtensionCore(context); if (value is IFixupToken) { return(value); } ctorArgs.Add(value); } else { String membernameOrString = processString( ); if (membernameOrString.Length == 0) { throw new InvalidOperationException( String.Format("Syntax error: member name or string expected at {0}", index)); } if (peekNextChar( ) == '=') { consumeChar( ); object value = peekNextChar( ) == '{' ? processMarkupExtensionCore(context) : processString( ); if (value is IFixupToken) { return(value); } // construct object if not constructed yet if (obj == null) { obj = construct(type, ctorArgs); } // assign value to specified member assignProperty(type, obj, membernameOrString, value); } else if (peekNextChar( ) == ',' || peekNextChar( ) == '}') { // syntax error if ctor arg defined after any property if (obj != null) { throw new InvalidOperationException("Syntax error: constructor argument" + " cannot be after property assignment."); } // store membernameOrString as string argument of ctor ctorArgs.Add(membernameOrString); } else { // it is '{' token, throw syntax error throw new InvalidOperationException( String.Format("Syntax error : unexpected '{{' token at {0}.", index)); } } // after ctor arg or property assignment should be , or } if (peekNextChar( ) == ',') { consumeChar( ); } else if (peekNextChar( ) == '}') { consumeChar( ); // construct object if (obj == null) { obj = construct(type, ctorArgs); } // markup extension is finished break; } else { // it is '{' token (without whitespace), throw syntax error throw new InvalidOperationException( String.Format("Syntax error : unexpected '{{' token at {0}.", index)); } processWhitespace(false); } return(((IMarkupExtension)obj).ProvideValue(context)); }