public static XamlObject Parse(string text, XamlObject parent, XmlAttribute attribute) { var tokens = MarkupExtensionTokenizer.Tokenize(text); if (tokens.Count < 3 || tokens[0].Kind != MarkupExtensionTokenKind.OpenBrace || tokens[1].Kind != MarkupExtensionTokenKind.TypeName || tokens[tokens.Count - 1].Kind != MarkupExtensionTokenKind.CloseBrace) { throw new XamlMarkupExtensionParseException("Invalid markup extension"); } var typeResolver = parent.ServiceProvider.Resolver; string typeName = tokens[1].Value; Type extensionType = typeResolver.Resolve(typeName + "Extension"); if (extensionType == null) { extensionType = typeResolver.Resolve(typeName); } if (extensionType == null || !typeof(MarkupExtension).IsAssignableFrom(extensionType)) { throw new XamlMarkupExtensionParseException("Unknown markup extension " + typeName + "Extension"); } List <string> positionalArgs = new List <string>(); List <KeyValuePair <string, string> > namedArgs = new List <KeyValuePair <string, string> >(); for (int i = 2; i < tokens.Count - 1; i++) { if (tokens[i].Kind == MarkupExtensionTokenKind.String) { positionalArgs.Add(tokens[i].Value); } else if (tokens[i].Kind == MarkupExtensionTokenKind.Membername) { if (tokens[i + 1].Kind != MarkupExtensionTokenKind.Equals || tokens[i + 2].Kind != MarkupExtensionTokenKind.String) { throw new XamlMarkupExtensionParseException("Invalid markup extension"); } namedArgs.Add(new KeyValuePair <string, string>(tokens[i].Value, tokens[i + 2].Value)); i += 2; } } // Find the constructor with positionalArgs.Count arguments var ctors = extensionType.GetConstructors().Where(c => c.GetParameters().Length == positionalArgs.Count).ToList(); if (ctors.Count < 1) { throw new XamlMarkupExtensionParseException("No constructor for " + extensionType.FullName + " found that takes " + positionalArgs.Count + " arguments"); } if (ctors.Count > 1) { Debug.WriteLine("Multiple constructors for " + extensionType.FullName + " found that take " + positionalArgs.Count + " arguments"); } var ctor = ctors[0]; var defaultCtor = extensionType.GetConstructor(Type.EmptyTypes); bool mappingToProperties = defaultCtor != null; List <PropertyInfo> map = new List <PropertyInfo>(); if (mappingToProperties) { foreach (var param in ctor.GetParameters()) { var prop = extensionType.GetProperty(param.Name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase); if (prop == null) { mappingToProperties = false; break; } map.Add(prop); } } object instance; if (mappingToProperties) { instance = defaultCtor.Invoke(null); } else { var ctorParamsInfo = ctor.GetParameters(); var ctorParams = new object[ctorParamsInfo.Length]; for (int i = 0; i < ctorParams.Length; i++) { var paramType = ctorParamsInfo[i].ParameterType; ctorParams[i] = XamlParser.CreateObjectFromAttributeText(positionalArgs[i], paramType, parent); } instance = ctor.Invoke(ctorParams); //TODO //XamlObject.ConstructorArgsProperty - args collection //Reinvoke ctor when needed } XamlObject result = parent.OwnerDocument.CreateObject(instance); if (attribute != null) { result.XmlAttribute = attribute; } result.ParentObject = parent; if (mappingToProperties) { for (int i = 0; i < positionalArgs.Count; i++) { var a = parent.OwnerDocument.XmlDocument.CreateAttribute(map[i].Name); a.Value = positionalArgs[i]; XamlParser.ParseObjectAttribute(result, a, false); } } foreach (var pair in namedArgs) { var a = parent.OwnerDocument.XmlDocument.CreateAttribute(pair.Key); a.Value = pair.Value; XamlParser.ParseObjectAttribute(result, a, false); } return(result); }