public void Visit(ElementNode node, INode parentNode) { var typeref = Module.ImportReference(node.XmlType.GetTypeReference(XmlTypeExtensions.ModeOfGetType.Both, Module, node)); if (IsXaml2009LanguagePrimitive(node)) { var vardef = new VariableDefinition(typeref); Context.Variables[node] = vardef; var value = GetValueFromLanguagePrimitive(typeref, node); Context.Values[node] = value; return; } TypeDefinition typedef = typeref.ResolveCached(); //if this is a MarkupExtension that can be compiled directly, compile and returns the value var compiledMarkupExtensionName = typeref .GetCustomAttribute(Module, (XamlTask.xamlAssemblyName, XamlTask.xamlNameSpace, "ProvideCompiledAttribute")) ?.ConstructorArguments?[0].Value as string; Type compiledMarkupExtensionType; ICompiledMarkupExtension markupProvider; if (compiledMarkupExtensionName != null && (compiledMarkupExtensionType = Type.GetType(compiledMarkupExtensionName)) != null && (markupProvider = Activator.CreateInstance(compiledMarkupExtensionType) as ICompiledMarkupExtension) != null) { Context.Values[node] = markupProvider.ProvideValue(node, Module, Context); VariableDefinition vardef = new VariableDefinition(typeref); Context.Variables[node] = vardef; //clean the node as it has been fully exhausted foreach (var prop in node.Properties) { if (!node.SkipProperties.Contains(prop.Key)) { node.SkipProperties.Add(prop.Key); } } node.CollectionItems.Clear(); return; } MethodDefinition factoryCtorInfo = null; MethodDefinition factoryMethodInfo = null; MethodDefinition parameterizedCtorInfo = null; MethodDefinition ctorInfo = null; if (node.Properties.ContainsKey(XmlName.xArguments) && !node.Properties.ContainsKey(XmlName.xFactoryMethod)) { factoryCtorInfo = typedef.AllMethods().FirstOrDefault(md => md.IsConstructor && !md.IsStatic && md.HasParameters && md.MatchXArguments(node, typeref, Module, Context)); if (factoryCtorInfo == null) { throw new XamlParseException( string.Format("No constructors found for {0} with matching x:Arguments", typedef.FullName), node); } ctorInfo = factoryCtorInfo; if (!typedef.IsValueType) //for ctor'ing typedefs, we first have to ldloca before the params { VariableDefinition vardef = new VariableDefinition(typeref); Context.Variables[node] = vardef; var argumentList = GetCtorXArguments(node, factoryCtorInfo.Parameters.Count, true); Context.Values[node] = new EXamlCreateObject(Context, null, typedef, argumentList.ToArray()); return; } } else if (node.Properties.ContainsKey(XmlName.xFactoryMethod)) { var factoryMethod = (string)(node.Properties[XmlName.xFactoryMethod] as ValueNode).Value; factoryMethodInfo = typedef.AllMethods().FirstOrDefault(md => !md.IsConstructor && md.Name == factoryMethod && md.IsStatic && md.MatchXArguments(node, typeref, Module, Context)); if (factoryMethodInfo == null) { var typeExtensionRef = Module.ImportReference(node.XmlType.GetTypeReference(XmlTypeExtensions.ModeOfGetType.OnlyGetTypeExtension, Module, node)); typeExtensionRef = typeExtensionRef?.ResolveCached(); if (null != typeExtensionRef) { factoryMethodInfo = typeExtensionRef.ResolveCached().AllMethods().FirstOrDefault(md => !md.IsConstructor && md.Name == factoryMethod && md.IsStatic && md.MatchXArguments(node, typeExtensionRef, Module, Context)); } } if (factoryMethodInfo == null) { throw new XamlParseException( String.Format("No static method found for {0}::{1} ({2})", typedef.FullName, factoryMethod, null), node); } VariableDefinition vardef = new VariableDefinition(typeref); Context.Variables[node] = vardef; var argumentList = GetCtorXArguments(node, factoryMethodInfo.Parameters.Count, false); Context.Values[node] = new EXamlCreateObject(Context, null, typedef, factoryMethodInfo, argumentList?.ToArray()); return; } if (ctorInfo == null && factoryMethodInfo == null) { parameterizedCtorInfo = typedef.Methods.FirstOrDefault(md => md.IsConstructor && !md.IsStatic && md.HasParameters && md.Parameters.All( pd => pd.CustomAttributes.Any( ca => ca.AttributeType.FullName == "Tizen.NUI.Binding.ParameterAttribute"))); } string missingCtorParameter = null; List <object> parameterizedCtorParams = null; if (parameterizedCtorInfo != null && ValidateCtorArguments(parameterizedCtorInfo, node, out missingCtorParameter)) { ctorInfo = parameterizedCtorInfo; parameterizedCtorParams = GetCtorArguments(parameterizedCtorInfo, node, Context); //Fang //IL_0000: ldstr "foo" //Context.IL.Append(PushCtorArguments(parameterizedCtorInfo, node)); } ctorInfo = ctorInfo ?? typedef.Methods.FirstOrDefault(md => md.IsConstructor && !md.HasParameters && !md.IsStatic); if (null == ctorInfo) { foreach (var method in typedef.Methods) { if (method.IsConstructor && !method.IsStatic) { bool areAllParamsDefault = true; foreach (var param in method.Parameters) { if (!param.HasDefault) { areAllParamsDefault = false; break; } } if (areAllParamsDefault) { if (null == ctorInfo) { ctorInfo = method; } else { throw new XamlParseException($"{typedef.FullName} has more than one constructor which params are all default.", node); } } } } if (null == ctorInfo && !typedef.IsValueType) { throw new XamlParseException($"{typedef.FullName} has no constructor which params are all default.", node); } } if (parameterizedCtorInfo != null && ctorInfo == null) { //there was a parameterized ctor, we didn't use it throw new XamlParseException($"The Property '{missingCtorParameter}' is required to create a '{typedef.FullName}' object.", node); } var ctorinforef = ctorInfo?.ResolveGenericParameters(typeref, Module); var factorymethodinforef = factoryMethodInfo?.ResolveGenericParameters(typeref, Module); var implicitOperatorref = typedef.Methods.FirstOrDefault(md => md.IsPublic && md.IsStatic && md.IsSpecialName && md.Name == "op_Implicit" && md.Parameters[0].ParameterType.FullName == "System.String"); if (ctorinforef != null || factorymethodinforef != null || typedef.IsValueType) { VariableDefinition vardef = new VariableDefinition(typeref); Context.Variables[node] = vardef; ValueNode vnode = null; if (node.CollectionItems.Count == 1 && (vnode = node.CollectionItems.First() as ValueNode) != null && vardef.VariableType.IsValueType) { Context.Values[node] = vnode.GetBaseValue(Context, typeref); } else if (node.CollectionItems.Count == 1 && (vnode = node.CollectionItems.First() as ValueNode) != null && implicitOperatorref != null) { var converterType = vnode.GetConverterType(new ICustomAttributeProvider[] { typeref.ResolveCached() }); if (null == converterType) { var realValue = vnode.GetBaseValue(Context, typeref); Context.Values[node] = new EXamlCreateObject(Context, realValue, typeref); } else { var converterValue = new EXamlValueConverterFromString(Context, converterType.Resolve(), vnode.Value as string); Context.Values[node] = new EXamlCreateObject(Context, converterValue, typeref); } } else if (factorymethodinforef != null) { //Fang //Context.IL.Emit(OpCodes.Call, Module.ImportReference(factorymethodinforef)); //Context.IL.Emit(OpCodes.Stloc, vardef); } else if (!typedef.IsValueType) { var ctor = Module.ImportReference(ctorinforef); //IL_0001: newobj instance void class [Tizen.NUI.Xaml.UIComponents]Tizen.NUI.Xaml.UIComponents.Button::'.ctor'() //IL_0006: stloc.0 //Context.IL.Emit(OpCodes.Newobj, ctor); //Context.IL.Emit(OpCodes.Stloc, vardef); if (typeref.FullName == "Tizen.NUI.Xaml.ArrayExtension") { typeref = Module.ImportReference(typeof(ArrayExtension)); } var accordingType = this.GetType().Assembly.GetType(typeref.FullName); if (null != accordingType && accordingType != typeof(Binding.Setter) && accordingType != typeof(ResourceDictionary)) { Context.Values[node] = new EXamlCreateObject(Context, Activator.CreateInstance(accordingType), typeref); } else if (null != parameterizedCtorParams) { Context.Values[node] = new EXamlCreateObject(Context, null, typeref, parameterizedCtorParams.ToArray()); } else { bool canConvertCollectionItem = false; if (!typeref.InheritsFromOrImplements(Context.Module.ImportReference(typeof(List <string>)).Resolve()) && node.CollectionItems.Count == 1 && (vnode = node.CollectionItems.First() as ValueNode) != null) { var valueNode = node.CollectionItems.First() as ValueNode; if (valueNode.CanConvertValue(Context.Module, typeref, (TypeReference)null)) { var converterType = valueNode.GetConverterType(new ICustomAttributeProvider[] { typeref.Resolve() }); if (null != converterType) { var converterValue = new EXamlValueConverterFromString(Context, converterType.Resolve(), valueNode.Value as string); Context.Values[node] = new EXamlCreateObject(Context, converterValue, typeref); } else { var valueItem = valueNode.GetBaseValue(Context, typeref); if (null == valueItem) { throw new XamlParseException($"Can't convert collection item \"{vnode.Value}\" to object", node); } Context.Values[node] = valueItem; } canConvertCollectionItem = true; } } if (false == canConvertCollectionItem) { if (!ctorInfo.HasParameters) { Context.Values[node] = new EXamlCreateObject(Context, null, typeref); } else { object[] @params = new object[ctorInfo.Parameters.Count]; for (int i = 0; i < ctorInfo.Parameters.Count; i++) { var param = ctorInfo.Parameters[i]; if (ctorInfo.Parameters[i].ParameterType.ResolveCached().IsEnum) { @params[i] = NodeILExtensions.GetParsedEnum(Context, param.ParameterType, param.Constant.ToString()); } else { @params[i] = param.Constant; } } Context.Values[node] = new EXamlCreateObject(Context, null, typeref, @params); } } } } else if (ctorInfo != null && node.Properties.ContainsKey(XmlName.xArguments) && !node.Properties.ContainsKey(XmlName.xFactoryMethod) && ctorInfo.MatchXArguments(node, typeref, Module, Context)) { var argumentList = GetCtorXArguments(node, factoryCtorInfo.Parameters.Count, true); Context.Values[node] = new EXamlCreateObject(Context, null, typedef, argumentList.ToArray()); return; } else { Context.Values[node] = new EXamlCreateObject(Context, null, typedef, null); return; } if (typeref.FullName == "Tizen.NUI.Xaml.ArrayExtension") { //Fang //var visitor = new SetPropertiesVisitor(Context); //foreach (var cnode in node.Properties.Values.ToList()) // cnode.Accept(visitor, node); //foreach (var cnode in node.CollectionItems) // cnode.Accept(visitor, node); //markupProvider = new ArrayExtension(); //var il = markupProvider.ProvideValue(node, Module, Context, out typeref); //vardef = new VariableDefinition(typeref); //Context.Variables[node] = vardef; //Context.Body.Variables.Add(vardef); //Context.IL.Append(il); //Context.IL.Emit(OpCodes.Stloc, vardef); ////clean the node as it has been fully exhausted //foreach (var prop in node.Properties) // if (!node.SkipProperties.Contains(prop.Key)) // node.SkipProperties.Add(prop.Key); //node.CollectionItems.Clear(); return; } } }