[NUI][XamlBuild] Fix Xaml issues reported by VD
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI.XamlBuild / src / public / EXamlBuild / EXamlCreateObjectVisitor.cs
1 /*
2  * Copyright(c) 2022 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17 using System;
18 using System.Collections.Generic;
19 using System.Globalization;
20 using System.Linq;
21 using Mono.Cecil;
22 using Mono.Cecil.Cil;
23 using Tizen.NUI.Xaml;
24 using System.Xml;
25
26 using static Mono.Cecil.Cil.Instruction;
27 using static Mono.Cecil.Cil.OpCodes;
28 using Tizen.NUI.Xaml.Build.Tasks;
29 using ArrayExtension = Tizen.NUI.Xaml.Build.Tasks.ArrayExtension;
30
31 namespace Tizen.NUI.EXaml.Build.Tasks
32 {
33     class EXamlCreateObjectVisitor : IXamlNodeVisitor
34     {
35         public EXamlCreateObjectVisitor(EXamlContext context)
36         {
37             Context = context;
38             Module = context.Module;
39         }
40
41         public EXamlContext Context { get; }
42
43         ModuleDefinition Module { get; }
44
45         public TreeVisitingMode VisitingMode => TreeVisitingMode.BottomUp;
46         public bool StopOnDataTemplate => true;
47         public bool StopOnResourceDictionary => false;
48         public bool VisitNodeOnDataTemplate => false;
49         public bool SkipChildren(INode node, INode parentNode) => false;
50
51         public bool IsResourceDictionary(ElementNode node)
52         {
53             var parentVar = Context.Variables[(IElementNode)node];
54             return parentVar.VariableType.FullName == "Tizen.NUI.Binding.ResourceDictionary"
55                 || parentVar.VariableType.Resolve().BaseType?.FullName == "Tizen.NUI.Binding.ResourceDictionary";
56         }
57
58         public void Visit(ValueNode node, INode parentNode)
59         {
60             Context.Values[node] = node.Value;
61         }
62
63         public void Visit(MarkupNode node, INode parentNode)
64         {
65             //At this point, all MarkupNodes are expanded to ElementNodes
66         }
67
68         public void Visit(ElementNode node, INode parentNode)
69         {
70             var typeref = Module.ImportReference(node.XmlType.GetTypeReference(Module, node));
71
72             if (IsXaml2009LanguagePrimitive(node))
73             {
74                 var vardef = new VariableDefinition(typeref);
75                 Context.Variables[node] = vardef;
76
77                 var value = GetValueFromLanguagePrimitive(typeref, node);
78
79                 Context.Values[node] = value;
80                 return;
81             }
82
83             TypeDefinition typedef = typeref.ResolveCached();
84
85             //if this is a MarkupExtension that can be compiled directly, compile and returns the value
86             var compiledMarkupExtensionName = typeref
87                 .GetCustomAttribute(Module, (XamlTask.xamlAssemblyName, XamlTask.xamlNameSpace, "ProvideCompiledAttribute"))
88                 ?.ConstructorArguments?[0].Value as string;
89             Type compiledMarkupExtensionType;
90             ICompiledMarkupExtension markupProvider;
91             if (compiledMarkupExtensionName != null &&
92                 (compiledMarkupExtensionType = Type.GetType(compiledMarkupExtensionName)) != null &&
93                 (markupProvider = Activator.CreateInstance(compiledMarkupExtensionType) as ICompiledMarkupExtension) != null)
94             {
95
96                 Context.Values[node] = markupProvider.ProvideValue(node, Module, Context);
97
98                 VariableDefinition vardef = new VariableDefinition(typeref);
99                 Context.Variables[node] = vardef;
100
101                 //clean the node as it has been fully exhausted
102                 foreach (var prop in node.Properties)
103                     if (!node.SkipProperties.Contains(prop.Key))
104                         node.SkipProperties.Add(prop.Key);
105                 node.CollectionItems.Clear();
106                 return;
107             }
108
109             MethodDefinition factoryCtorInfo = null;
110             MethodDefinition factoryMethodInfo = null;
111             MethodDefinition parameterizedCtorInfo = null;
112             MethodDefinition ctorInfo = null;
113
114             if (node.Properties.ContainsKey(XmlName.xArguments) && !node.Properties.ContainsKey(XmlName.xFactoryMethod))
115             {
116                 factoryCtorInfo = typedef.AllMethods().FirstOrDefault(md => md.IsConstructor &&
117                                                                             !md.IsStatic &&
118                                                                             md.HasParameters &&
119                                                                             md.MatchXArguments(node, typeref, Module, Context));
120                 if (factoryCtorInfo == null)
121                 {
122                     throw new XamlParseException(
123                         string.Format("No constructors found for {0} with matching x:Arguments", typedef.FullName), node);
124                 }
125                 ctorInfo = factoryCtorInfo;
126                 if (!typedef.IsValueType) //for ctor'ing typedefs, we first have to ldloca before the params
127                 {
128                     VariableDefinition vardef = new VariableDefinition(typeref);
129                     Context.Variables[node] = vardef;
130
131                     var argumentList = GetCtorXArguments(node, factoryCtorInfo.Parameters.Count, true);
132                     Context.Values[node] = new EXamlCreateObject(Context, null, typedef, argumentList.ToArray());
133                     return;
134                 }
135             }
136             else if (node.Properties.ContainsKey(XmlName.xFactoryMethod))
137             {
138                 var factoryMethod = (string)(node.Properties[XmlName.xFactoryMethod] as ValueNode).Value;
139                 factoryMethodInfo = typedef.AllMethods().FirstOrDefault(md => !md.IsConstructor &&
140                                                                               md.Name == factoryMethod &&
141                                                                               md.IsStatic &&
142                                                                               md.MatchXArguments(node, typeref, Module, Context));
143
144                 if (factoryMethodInfo == null)
145                 {
146                     var typeExtensionRef = Module.ImportReference(node.XmlType.GetTypeExtensionReference(Module, node));
147                     typeExtensionRef = typeExtensionRef?.ResolveCached();
148
149                     if (null != typeExtensionRef)
150                     {
151                         factoryMethodInfo = typeExtensionRef.ResolveCached().AllMethods().FirstOrDefault(md => !md.IsConstructor &&
152                                                                               md.Name == factoryMethod &&
153                                                                               md.IsStatic &&
154                                                                               md.MatchXArguments(node, typeExtensionRef, Module, Context));
155                     }
156                 }
157
158                 if (factoryMethodInfo == null)
159                 {
160                     throw new XamlParseException(
161                         String.Format("No static method found for {0}::{1} ({2})", typedef.FullName, factoryMethod, null), node);
162                 }
163
164                 VariableDefinition vardef = new VariableDefinition(typeref);
165                 Context.Variables[node] = vardef;
166
167                 var argumentList = GetCtorXArguments(node, factoryMethodInfo.Parameters.Count, false);
168                 Context.Values[node] = new EXamlCreateObject(Context, null, typedef, factoryMethodInfo, argumentList?.ToArray());
169                 return;
170             }
171
172             if (ctorInfo == null && factoryMethodInfo == null)
173             {
174                 parameterizedCtorInfo = typedef.Methods.FirstOrDefault(md => md.IsConstructor &&
175                                                                              !md.IsStatic &&
176                                                                              md.HasParameters &&
177                                                                              md.Parameters.All(
178                                                                                  pd =>
179                                                                                      pd.CustomAttributes.Any(
180                                                                                          ca =>
181                                                                                              ca.AttributeType.FullName ==
182                                                                                              "Tizen.NUI.Binding.ParameterAttribute")));
183             }
184             string missingCtorParameter = null;
185             List<object> parameterizedCtorParams = null;
186
187             if (parameterizedCtorInfo != null && ValidateCtorArguments(parameterizedCtorInfo, node, out missingCtorParameter))
188             {
189                 ctorInfo = parameterizedCtorInfo;
190                 parameterizedCtorParams = GetCtorArguments(parameterizedCtorInfo, node, Context);
191                 //Fang
192                 //IL_0000:  ldstr "foo"
193                 //Context.IL.Append(PushCtorArguments(parameterizedCtorInfo, node));
194             }
195
196             ctorInfo = ctorInfo ?? typedef.Methods.FirstOrDefault(md => md.IsConstructor && !md.HasParameters && !md.IsStatic);
197
198             if (null == ctorInfo)
199             {
200                 foreach (var method in typedef.Methods)
201                 {
202                     if (method.IsConstructor && !method.IsStatic)
203                     {
204                         bool areAllParamsDefault = true;
205
206                         foreach (var param in method.Parameters)
207                         {
208                             if (!param.HasDefault)
209                             {
210                                 areAllParamsDefault = false;
211                                 break;
212                             }
213                         }
214
215                         if (areAllParamsDefault)
216                         {
217                             if (null == ctorInfo)
218                             {
219                                 ctorInfo = method;
220                             }
221                             else
222                             {
223                                 throw new XamlParseException($"{typedef.FullName} has more than one constructor which params are all default.", node);
224                             }
225                         }
226                     }
227                 }
228
229                 if (null == ctorInfo && !typedef.IsValueType)
230                 {
231                     throw new XamlParseException($"{typedef.FullName} has no constructor which params are all default.", node);
232                 }
233             }
234
235             if (parameterizedCtorInfo != null && ctorInfo == null)
236                 //there was a parameterized ctor, we didn't use it
237                 throw new XamlParseException($"The Property '{missingCtorParameter}' is required to create a '{typedef.FullName}' object.", node);
238             var ctorinforef = ctorInfo?.ResolveGenericParameters(typeref, Module);
239
240             var factorymethodinforef = factoryMethodInfo?.ResolveGenericParameters(typeref, Module);
241             var implicitOperatorref = typedef.Methods.FirstOrDefault(md =>
242                 md.IsPublic &&
243                 md.IsStatic &&
244                 md.IsSpecialName &&
245                 md.Name == "op_Implicit" && md.Parameters[0].ParameterType.FullName == "System.String");
246
247             if (ctorinforef != null || factorymethodinforef != null || typedef.IsValueType)
248             {
249                 VariableDefinition vardef = new VariableDefinition(typeref);
250                 Context.Variables[node] = vardef;
251
252                 ValueNode vnode = null;
253                 if (node.CollectionItems.Count == 1 && (vnode = node.CollectionItems.First() as ValueNode) != null &&
254                     vardef.VariableType.IsValueType)
255                 {
256                     Context.Values[node] = vnode.GetBaseValue(Context, typeref);
257                 }
258                 else if (node.CollectionItems.Count == 1 && (vnode = node.CollectionItems.First() as ValueNode) != null &&
259                            implicitOperatorref != null)
260                 {
261                     var converterType = vnode.GetConverterType(new ICustomAttributeProvider[] { typeref.ResolveCached() });
262                     if (null == converterType)
263                     {
264                         var realValue = vnode.GetBaseValue(Context, typeref);
265                         Context.Values[node] = new EXamlCreateObject(Context, realValue, typeref);
266                     }
267                     else
268                     {
269                         var converterValue = new EXamlValueConverterFromString(Context, converterType.Resolve(), vnode.Value as string);
270                         Context.Values[node] = new EXamlCreateObject(Context, converterValue, typeref);
271                     }
272                 }
273                 else if (factorymethodinforef != null)
274                 {
275                     //Fang
276                     //Context.IL.Emit(OpCodes.Call, Module.ImportReference(factorymethodinforef));
277                     //Context.IL.Emit(OpCodes.Stloc, vardef);
278                 }
279                 else if (!typedef.IsValueType)
280                 {
281                     var ctor = Module.ImportReference(ctorinforef);
282                     //IL_0001:  newobj instance void class [Tizen.NUI.Xaml.UIComponents]Tizen.NUI.Xaml.UIComponents.Button::'.ctor'()
283                     //IL_0006:  stloc.0
284                     //Context.IL.Emit(OpCodes.Newobj, ctor);
285                     //Context.IL.Emit(OpCodes.Stloc, vardef);
286                     if (typeref.FullName == "Tizen.NUI.Xaml.ArrayExtension")
287                     {
288                         typeref = Module.ImportReference(typeof(ArrayExtension));
289                         typedef = typeref.ResolveCached();
290                     }
291
292                     var accordingType = this.GetType().Assembly.GetType(typedef.FullName);
293
294                     if (null != accordingType && accordingType != typeof(Binding.Setter))
295                     {
296                         Context.Values[node] = new EXamlCreateObject(Context, Activator.CreateInstance(accordingType), typeref);
297                     }
298                     else if (null != parameterizedCtorParams)
299                     {
300                         Context.Values[node] = new EXamlCreateObject(Context, null, typeref, parameterizedCtorParams.ToArray());
301                     }
302                     else
303                     {
304                         bool canConvertCollectionItem = false;
305
306                         if (!typeref.InheritsFromOrImplements(Context.Module.ImportReference(typeof(List<string>)).Resolve())
307                             &&
308                             node.CollectionItems.Count == 1 && (vnode = node.CollectionItems.First() as ValueNode) != null)
309                         {
310                             var valueNode = node.CollectionItems.First() as ValueNode;
311
312                             if (valueNode.CanConvertValue(Context.Module, typeref, (TypeReference)null))
313                             {
314                                 var converterType = valueNode.GetConverterType(new ICustomAttributeProvider[] { typeref.Resolve() });
315                                 if (null != converterType)
316                                 {
317                                     var converterValue = new EXamlValueConverterFromString(Context, converterType.Resolve(), valueNode.Value as string);
318                                     Context.Values[node] = new EXamlCreateObject(Context, converterValue, typeref);
319                                 }
320                                 else
321                                 {
322                                     var valueItem = valueNode.GetBaseValue(Context, typeref);
323                                     if (null == valueItem)
324                                     {
325                                         throw new XamlParseException($"Can't convert collection item \"{vnode.Value}\" to object", node);
326                                     }
327
328                                     Context.Values[node] = valueItem;
329                                 }
330
331                                 canConvertCollectionItem = true;
332                             }
333                         }
334
335                         if (false == canConvertCollectionItem)
336                         {
337                             if (!ctorInfo.HasParameters)
338                             {
339                                 Context.Values[node] = new EXamlCreateObject(Context, null, typeref);
340                             }
341                             else
342                             {
343                                 object[] @params = new object[ctorInfo.Parameters.Count];
344
345                                 for (int i = 0; i < ctorInfo.Parameters.Count; i++)
346                                 {
347                                     var param = ctorInfo.Parameters[i];
348
349                                     if (ctorInfo.Parameters[i].ParameterType.ResolveCached().IsEnum)
350                                     {
351                                         @params[i] = NodeILExtensions.GetParsedEnum(Context, param.ParameterType, param.Constant.ToString());
352                                     }
353                                     else
354                                     {
355                                         @params[i] = param.Constant;
356                                     }
357                                 }
358
359                                 Context.Values[node] = new EXamlCreateObject(Context, null, typeref, @params);
360                             }
361                         }
362                     }
363                 }
364                 else if (ctorInfo != null && node.Properties.ContainsKey(XmlName.xArguments) &&
365                          !node.Properties.ContainsKey(XmlName.xFactoryMethod) && ctorInfo.MatchXArguments(node, typeref, Module, Context))
366                 {
367                     //IL_0008:  ldloca.s 1
368                     //IL_000a:  ldc.i4.1 
369                     //IL_000b:  call instance void valuetype Test/Foo::'.ctor'(bool)
370
371                     //Fang
372                     //var ctor = Module.ImportReference(ctorinforef);
373                     //Context.IL.Emit(OpCodes.Ldloca, vardef);
374                     //Context.IL.Append(PushCtorXArguments(factoryCtorInfo, node));
375                     //Context.IL.Emit(OpCodes.Call, ctor);
376                 }
377                 else
378                 {
379                     //IL_0000:  ldloca.s 0
380                     //IL_0002:  initobj Test/Foo
381                     //Fang
382                     //Context.IL.Emit(OpCodes.Ldloca, vardef);
383                     //Context.IL.Emit(OpCodes.Initobj, Module.ImportReference(typedef));
384                 }
385
386                 if (typeref.FullName == "Tizen.NUI.Xaml.ArrayExtension")
387                 {
388                     //Fang
389                     //var visitor = new SetPropertiesVisitor(Context);
390                     //foreach (var cnode in node.Properties.Values.ToList())
391                     //    cnode.Accept(visitor, node);
392                     //foreach (var cnode in node.CollectionItems)
393                     //    cnode.Accept(visitor, node);
394
395                     //markupProvider = new ArrayExtension();
396
397                     //var il = markupProvider.ProvideValue(node, Module, Context, out typeref);
398
399                     //vardef = new VariableDefinition(typeref);
400                     //Context.Variables[node] = vardef;
401                     //Context.Body.Variables.Add(vardef);
402
403                     //Context.IL.Append(il);
404                     //Context.IL.Emit(OpCodes.Stloc, vardef);
405
406                     ////clean the node as it has been fully exhausted
407                     //foreach (var prop in node.Properties)
408                     //    if (!node.SkipProperties.Contains(prop.Key))
409                     //        node.SkipProperties.Add(prop.Key);
410                     //node.CollectionItems.Clear();
411
412                     return;
413                 }
414             }
415         }
416
417         public void Visit(RootNode node, INode parentNode)
418         {
419             //IL_0013:  ldarg.0 
420             //IL_0014:  stloc.3 
421
422             var ilnode = (ILRootNode)node;
423             var typeref = ilnode.TypeReference;
424             var vardef = new VariableDefinition(typeref);
425             Context.Variables[node] = vardef;
426             Context.Root = vardef;
427             Context.RootNode = node;
428             //Context.IL.Emit(OpCodes.Ldarg_0);
429             //Context.IL.Emit(OpCodes.Stloc, vardef);
430         }
431
432         public void Visit(ListNode node, INode parentNode)
433         {
434             XmlName name;
435             if (EXamlSetPropertiesVisitor.TryGetPropertyName(node, parentNode, out name))
436                 node.XmlName = name;
437         }
438
439         bool ValidateCtorArguments(MethodDefinition ctorinfo, ElementNode enode, out string firstMissingProperty)
440         {
441             firstMissingProperty = null;
442             foreach (var parameter in ctorinfo.Parameters)
443             {
444                 var propname =
445                     parameter.CustomAttributes.First(ca => ca.AttributeType.FullName == "Tizen.NUI.Binding.ParameterAttribute")
446                         .ConstructorArguments.First()
447                         .Value as string;
448                 if (!enode.Properties.ContainsKey(new XmlName("", propname)))
449                 {
450                     firstMissingProperty = propname;
451                     return false;
452                 }
453             }
454             return true;
455         }
456
457         List<object> GetCtorXArguments(ElementNode enode, int paramsCount, bool isConstructor)
458         {
459             if (!enode.Properties.ContainsKey(XmlName.xArguments))
460             {
461                 return null;
462             }
463
464             List<object> argumentList = new List<object>();
465
466             var arguments = new List<INode>();
467             var node = enode.Properties[XmlName.xArguments] as ElementNode;
468             if (node != null)
469             {
470                 node.Accept(new EXamlSetPropertiesVisitor(Context, true), null);
471                 arguments.Add(node);
472             }
473
474             var list = enode.Properties[XmlName.xArguments] as ListNode;
475             if (list != null)
476             {
477                 foreach (var n in list.CollectionItems)
478                     arguments.Add(n);
479             }
480
481             for (int i = 0; i < arguments.Count; i++)
482             {
483                 argumentList.Add(Context.Values[arguments[i]]);
484             }
485
486             if (!isConstructor)
487             {
488                 for (int i = arguments.Count; i < paramsCount; i++)
489                 {
490                     argumentList.Add(Type.Missing);
491                 }
492             }
493
494             return argumentList;
495         }
496
497         static bool IsXaml2009LanguagePrimitive(IElementNode node)
498         {
499             if (node.NamespaceURI == XamlParser.X2009Uri)
500             {
501                 var n = node.XmlType.Name.Split(':')[1];
502                 return n != "Array";
503             }
504             if (node.NamespaceURI != "clr-namespace:System;assembly=mscorlib")
505                 return false;
506             var name = node.XmlType.Name.Split(':')[1];
507             if (name == "SByte" ||
508                 name == "Int16" ||
509                 name == "Int32" ||
510                 name == "Int64" ||
511                 name == "Byte" ||
512                 name == "UInt16" ||
513                 name == "UInt32" ||
514                 name == "UInt64" ||
515                 name == "Single" ||
516                 name == "Double" ||
517                 name == "Boolean" ||
518                 name == "String" ||
519                 name == "Char" ||
520                 name == "Decimal" ||
521                 name == "TimeSpan" ||
522                 name == "Uri")
523                 return true;
524             return false;
525         }
526
527         object GetValueFromLanguagePrimitive(TypeReference typeRef, ElementNode node)
528         {
529             var module = Context.Module;
530             var hasValue = node.CollectionItems.Count == 1 && node.CollectionItems[0] is ValueNode &&
531                            ((ValueNode)node.CollectionItems[0]).Value is string;
532             var valueString = hasValue ? ((ValueNode)node.CollectionItems[0]).Value as string : string.Empty;
533             object ret = null;
534
535             TypeDefinition typedef = typeRef.ResolveCached();
536
537             switch (typedef.FullName)
538             {
539                 case "System.SByte":
540                     if (hasValue && sbyte.TryParse(valueString, NumberStyles.Number, CultureInfo.InvariantCulture, out sbyte outsbyte))
541                         ret = outsbyte;
542                     else
543                         ret = 0;
544                     break;
545                 case "System.Int16":
546                     if (hasValue && short.TryParse(valueString, NumberStyles.Number, CultureInfo.InvariantCulture, out short outshort))
547                         ret = outshort;
548                     else
549                         ret = 0;
550                     break;
551                 case "System.Int32":
552                     if (hasValue && int.TryParse(valueString, NumberStyles.Number, CultureInfo.InvariantCulture, out int outint))
553                         ret = outint;
554                     else
555                         ret = 0;
556                     break;
557                 case "System.Int64":
558                     if (hasValue && long.TryParse(valueString, NumberStyles.Number, CultureInfo.InvariantCulture, out long outlong))
559                         ret = outlong;
560                     else
561                         ret = 0;
562                     break;
563                 case "System.Byte":
564                     if (hasValue && byte.TryParse(valueString, NumberStyles.Number, CultureInfo.InvariantCulture, out byte outbyte))
565                         ret = outbyte;
566                     else
567                         ret = 0;
568                     break;
569                 case "System.UInt16":
570                     if (hasValue && short.TryParse(valueString, NumberStyles.Number, CultureInfo.InvariantCulture, out short outushort))
571                         ret = outushort;
572                     else
573                         ret = 0;
574                     break;
575                 case "System.UInt32":
576                     if (hasValue && uint.TryParse(valueString, NumberStyles.Number, CultureInfo.InvariantCulture, out uint outuint))
577                         ret = outuint;
578                     else
579                         ret = 0;
580                     break;
581                 case "System.UInt64":
582                     if (hasValue && long.TryParse(valueString, NumberStyles.Number, CultureInfo.InvariantCulture, out long outulong))
583                         ret = outulong;
584                     else
585                         ret = 0;
586                     break;
587                 case "System.Boolean":
588                     if (hasValue && bool.TryParse(valueString, out bool outbool))
589                         ret = true;
590                     else
591                         ret = false;
592                     break;
593                 case "System.String":
594                     ret = valueString;
595                     break;
596                 case "System.Object":
597                     var ctorinfo =
598                         module.TypeSystem.Object.ResolveCached()
599                             .Methods.FirstOrDefault(md => md.IsConstructor && !md.HasParameters);
600                     var ctor = module.ImportReference(ctorinfo);
601                     ret = Create(Newobj, ctor);
602                     break;
603                 case "System.Char":
604                     if (hasValue && char.TryParse(valueString, out char outchar))
605                         ret = outchar;
606                     else
607                         ret = (char)0;
608                     break;
609                 case "System.Decimal":
610                     decimal outdecimal;
611                     if (hasValue && decimal.TryParse(valueString, NumberStyles.Number, CultureInfo.InvariantCulture, out outdecimal))
612                     {
613                         ret = outdecimal;
614                     }
615                     else
616                     {
617                         ret = (decimal)0;
618                     }
619                     break;
620                 case "System.Single":
621                     if (hasValue && float.TryParse(valueString, NumberStyles.Number, CultureInfo.InvariantCulture, out float outfloat))
622                         ret = outfloat;
623                     else
624                         ret = 0f;
625                     break;
626                 case "System.Double":
627                     if (hasValue && double.TryParse(valueString, NumberStyles.Number, CultureInfo.InvariantCulture, out double outdouble))
628                         ret = outdouble;
629                     else
630                         ret = 0d;
631                     break;
632                 case "System.TimeSpan":
633                     if (hasValue && TimeSpan.TryParse(valueString, CultureInfo.InvariantCulture, out TimeSpan outspan))
634                     {
635
636                         ret = outspan;
637                     }
638                     else
639                     {
640                         ret = null;
641                     }
642                     break;
643                 case "System.Uri":
644                     if (hasValue && Uri.TryCreate(valueString, UriKind.RelativeOrAbsolute, out Uri outuri))
645                     {
646                         ret = outuri;
647                     }
648                     else
649                     {
650                         ret = null;
651                     };
652                     break;
653                 default:
654                     ret = new EXamlCreateObject(Context, null, typeRef);
655                     break;
656             }
657
658             return ret;
659         }
660
661         List<object> GetCtorArguments(MethodDefinition ctorinfo, ElementNode enode, EXamlContext context)
662         {
663             List<object> ret = null;
664
665             foreach (var parameter in ctorinfo.Parameters)
666             {
667                 var propname =
668                     parameter.CustomAttributes.First(ca => ca.AttributeType.FullName == "Tizen.NUI.Binding.ParameterAttribute")
669                         .ConstructorArguments.First()
670                         .Value as string;
671                 var node = enode.Properties[new XmlName("", propname)];
672                 if (!enode.SkipProperties.Contains(new XmlName("", propname)))
673                     enode.SkipProperties.Add(new XmlName("", propname));
674
675                 if (node is ValueNode valueNode)
676                 {
677                     var valueType = parameter.ParameterType;
678
679                     if ("System.Type" == valueType.FullName)
680                     {
681                         var typeRef = XmlTypeExtensions.GetTypeReference(valueNode.Value as string, Module, node as BaseNode);
682                         context.Values[node] = new EXamlCreateObject(context, typeRef);
683                     }
684                     else
685                     {
686                         var converterType = valueNode.GetConverterType(new ICustomAttributeProvider[] { parameter, parameter.ParameterType.ResolveCached() });
687
688                         if (null != converterType)
689                         {
690                             var converterValue = new EXamlValueConverterFromString(context, converterType.Resolve(), valueNode.Value as string);
691                             context.Values[node] = new EXamlCreateObject(context, converterValue, valueType);
692                         }
693                         else
694                         {
695                             context.Values[node] = valueNode.GetBaseValue(context, valueType);
696                         }
697                     }
698
699                     if (null == ret)
700                     {
701                         ret = new List<object>();
702                     }
703
704                     ret.Add(context.Values[node]);
705                 }
706             }
707
708             return ret;
709         }
710     }
711 }
712