5a990acd1621fb80368288730475be93aa415fe0
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI.XamlBuild / src / public / EXamlBuild / EXamlSetPropertiesVisitor.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.Linq;
20 using System.Xml;
21
22 using Mono.Cecil;
23 using Mono.Cecil.Cil;
24 using Mono.Cecil.Rocks;
25 using Tizen.NUI.Binding;
26 using Tizen.NUI.Binding.Internals;
27 using Tizen.NUI.EXaml;
28 using Tizen.NUI.Xaml;
29 using Tizen.NUI.Xaml.Build.Tasks;
30 using Tizen.NUI.Xaml.Core.XamlC;
31 using static Mono.Cecil.Cil.Instruction;
32 using static Mono.Cecil.Cil.OpCodes;
33
34 namespace Tizen.NUI.EXaml.Build.Tasks
35 {
36     class EXamlSetPropertiesVisitor : IXamlNodeVisitor
37     {
38         static int dtcount;
39         static int typedBindingCount;
40
41         static readonly IList<XmlName> skips = new List<XmlName>
42         {
43             XmlName.xKey,
44             XmlName.xTypeArguments,
45             XmlName.xArguments,
46             XmlName.xFactoryMethod,
47             XmlName.xName,
48             XmlName.xDataType
49         };
50
51         public EXamlSetPropertiesVisitor(EXamlContext context, bool stopOnResourceDictionary = false)
52         {
53             Context = context;
54             Module = context.Module;
55             StopOnResourceDictionary = stopOnResourceDictionary;
56         }
57
58         public EXamlContext Context { get; }
59         public bool StopOnResourceDictionary { get; }
60         public TreeVisitingMode VisitingMode => TreeVisitingMode.BottomUp;
61         public bool StopOnDataTemplate => true;
62         public bool VisitNodeOnDataTemplate => true;
63         public bool SkipChildren(INode node, INode parentNode) => false;
64
65         public bool IsResourceDictionary(ElementNode node)
66         {
67             var parentVar = Context.Values[node] as EXamlCreateObject;
68             return null != parentVar
69                     &&
70                     (parentVar.GetType().FullName == "Tizen.NUI.Binding.ResourceDictionary"
71                     || parentVar.GetType().Resolve().BaseType?.FullName == "Tizen.NUI.Binding.ResourceDictionary");
72         }
73
74         ModuleDefinition Module { get; }
75
76         public void Visit(ValueNode node, INode parentNode)
77         {
78             //TODO support Label text as element
79             XmlName propertyName;
80             if (!TryGetPropertyName(node, parentNode, out propertyName))
81             {
82                 if (!IsCollectionItem(node, parentNode))
83                     return;
84                 string contentProperty;
85                 if (!Context.Variables.ContainsKey((IElementNode)parentNode))
86                     return;
87                 var parentVar = Context.Variables[(IElementNode)parentNode];
88                 if ((contentProperty = GetContentProperty(parentVar.VariableType)) != null)
89                     propertyName = new XmlName(((IElementNode)parentNode).NamespaceURI, contentProperty);
90                 else
91                     return;
92             }
93
94             if (TrySetRuntimeName(propertyName, Context.Values[parentNode] as EXamlCreateObject, node))
95                 return;
96             if (skips.Contains(propertyName))
97                 return;
98             if (parentNode is IElementNode && ((IElementNode)parentNode).SkipProperties.Contains (propertyName))
99                 return;
100             if (propertyName.Equals(XamlParser.McUri, "Ignorable"))
101                 return;
102
103             SetPropertyValue(Context.Values[parentNode] as EXamlCreateObject, propertyName, node, Context, node);
104         }
105
106         public void Visit(MarkupNode node, INode parentNode)
107         {
108         }
109
110         public void Visit(ElementNode node, INode parentNode)
111         {
112             XmlName propertyName = XmlName.Empty;
113
114             //Simplify ListNodes with single elements
115             var pList = parentNode as ListNode;
116             if (pList != null
117                 &&
118                 (pList.CollectionItems.Count == 1
119                 ||
120                 "XamlResources" == pList.XmlName.LocalName))
121             {
122                 propertyName = pList.XmlName;
123                 parentNode = parentNode.Parent;
124             }
125
126             if ((propertyName != XmlName.Empty || TryGetPropertyName(node, parentNode, out propertyName)) && skips.Contains(propertyName))
127                 return;
128
129             if (propertyName == XmlName._CreateContent
130                 &&
131                 parentNode is ElementNode parentElementNode)
132             {
133                 SetDataTemplate(parentElementNode, node, Context, node);
134                 return;
135             }
136
137             //if this node is an IMarkupExtension, invoke ProvideValue() and replace the variable
138             var vardef = Context.Values[node];
139
140             var localName = propertyName.LocalName;
141             TypeReference declaringTypeReference = null;
142
143             PropertyDefinition propertyRef = null;
144             if (parentNode is IElementNode && propertyName != XmlName.Empty) {
145                 propertyRef = Context.Variables [(IElementNode)parentNode].VariableType.GetProperty(pd => pd.Name == localName, out declaringTypeReference);
146             }
147
148             if (vardef is EXamlCreateObject)
149             {
150                 var realValue = ProvideValue(vardef as EXamlCreateObject, Context, Module, node, propertyRef: propertyRef, propertyDeclaringTypeRef: declaringTypeReference);
151                 if (null != realValue && vardef != realValue)
152                 {
153                     (vardef as EXamlCreateObject).IsValid = false;
154                     Context.Values[node] = realValue;
155                     vardef = realValue;
156                 }
157             }
158
159             if (propertyName != XmlName.Empty) {
160                 if (skips.Contains(propertyName))
161                     return;
162                 if (parentNode is IElementNode && ((IElementNode)parentNode).SkipProperties.Contains (propertyName))
163                     return;
164                 
165                 SetPropertyValue(Context.Values[parentNode] as EXamlCreateObject, propertyName, node, Context, node);
166             }
167             else if (IsCollectionItem(node, parentNode) && parentNode is IElementNode) {
168                 var parentVar = Context.Values[parentNode] as EXamlCreateObject;
169                 string contentProperty;
170
171                 bool isAdded = false;
172
173                 if (CanAddToResourceDictionary(parentVar, parentVar.GetType(), node, node, Context))
174                 {
175                     var keyName = (node.Properties[XmlName.xKey] as ValueNode).Value as string;
176                     new EXamlAddToResourceDictionary(Context, parentVar, keyName, Context.Values[node]);
177                     isAdded = true;
178                 }
179                 
180                 // Collection element, implicit content, or implicit collection element.
181                 if (!isAdded && parentVar.GetType().GetMethods(md => md.Name == "Add" && md.Parameters.Count == 1, Module).Any())
182                 {
183                     var elementType = parentVar.GetType();
184                     var paramType = Context.Variables[node].VariableType;
185
186                     foreach (var adderTuple in elementType.GetMethods(md => md.Name == "Add" && md.Parameters.Count == 1, Module))
187                     {
188                         var adderRef = Module.ImportReference(adderTuple.Item1);
189                         adderRef = Module.ImportReference(adderRef.ResolveGenericParameters(adderTuple.Item2, Module));
190
191                         if (IsAddMethodOfCollection(Module, adderRef.Resolve()))
192                         {
193                             new EXamlAddToCollectionInstance(Context, parentVar, Context.Values[node]);
194                             isAdded = true;
195                             break;
196                         }
197                         else if (paramType.InheritsFromOrImplements(adderTuple.Item1.Parameters[0].ParameterType.FullName))
198                         {
199                             new EXamlAddObject(Context, parentVar, Context.Values[node], adderRef.Resolve());
200                             isAdded = true;
201                             break;
202                         }
203                     }
204                 }
205                 
206                 if (!isAdded && (contentProperty = GetContentProperty(parentVar.GetType())) != null)
207                 {
208                     var name = new XmlName(node.NamespaceURI, contentProperty);
209                     if (skips.Contains(name))
210                         return;
211                     if (parentNode is IElementNode && ((IElementNode)parentNode).SkipProperties.Contains(propertyName))
212                         return;
213                     
214                     SetPropertyValue(Context.Values[parentNode] as EXamlCreateObject, name, node, Context, node);
215                     isAdded = true;
216                 }
217                 
218                 if (!isAdded)
219                 {
220                     throw new XamlParseException($"Can not set the content of {((IElementNode)parentNode).XmlType.Name} as it doesn't have a ContentPropertyAttribute", node);
221                 }
222             }
223             else if (IsCollectionItem(node, parentNode) && parentNode is ListNode)
224             {
225                 var parentList = (ListNode)parentNode;
226                 if (skips.Contains(parentList.XmlName))
227                     return;
228                 if (parentNode is IElementNode && ((IElementNode)parentNode).SkipProperties.Contains (propertyName))
229                     return;
230
231                 var parent = Context.Variables[((IElementNode)parentNode.Parent)];
232                 var elementType = parent.VariableType;
233                 localName = parentList.XmlName.LocalName;
234
235                 if (Context.Values[parentList.Parent] is EXamlCreateObject)
236                 {
237                     if (localName.Contains('.'))
238                     {
239                         int index = localName.LastIndexOf('.');
240                         localName = localName.Substring(index + 1);
241                     }
242
243                     var getObjectByProperty = new EXamlGetObjectByProperty(Context, Context.Values[parentList.Parent] as EXamlCreateObject, localName);
244                     new EXamlAddToCollectionProperty(Context, getObjectByProperty, Context.Values[node]);
245                 }
246             }
247         }
248
249         public void Visit(RootNode node, INode parentNode)
250         {
251         }
252
253         public void Visit(ListNode node, INode parentNode)
254         {
255         }
256
257         private static MethodDefinition addDefOfCollection;
258         private static bool IsAddMethodOfCollection(ModuleDefinition module, MethodDefinition methodDef)
259         {
260             return module.ImportReference(typeof(List<string>)).InheritsFromOrImplements(methodDef.DeclaringType);
261         }
262
263         public static bool TryGetPropertyName(INode node, INode parentNode, out XmlName name)
264         {
265             name = default(XmlName);
266             var parentElement = parentNode as IElementNode;
267             if (parentElement == null)
268                 return false;
269             foreach (var kvp in parentElement.Properties)
270             {
271                 if (kvp.Value != node)
272                     continue;
273                 name = kvp.Key;
274                 return true;
275             }
276             return false;
277         }
278
279         static bool IsCollectionItem(INode node, INode parentNode)
280         {
281             var parentList = parentNode as IListNode;
282             if (parentList == null)
283                 return false;
284             return parentList.CollectionItems.Contains(node);
285         }
286
287         internal static string GetContentProperty(TypeReference typeRef)
288         {
289             var typeDef = typeRef.ResolveCached();
290             var attributes = typeDef.CustomAttributes;
291             var attr =
292                 attributes.FirstOrDefault(cad => ContentPropertyAttribute.ContentPropertyTypes.Contains(cad.AttributeType.FullName));
293             if (attr != null)
294                 return attr.ConstructorArguments[0].Value as string;
295             if (typeDef.BaseType == null)
296                 return null;
297             return GetContentProperty(typeDef.BaseType);
298         }
299
300         public static object ProvideValue(EXamlCreateObject instance, EXamlContext context,
301                                           ModuleDefinition module, ElementNode node,
302                                           PropertyReference propertyRef = null, TypeReference propertyDeclaringTypeRef = null)
303         {
304             GenericInstanceType markupExtension;
305             IList<TypeReference> genericArguments;
306             if (instance.GetType().FullName == "Tizen.NUI.Xaml.Build.Tasks.ArrayExtension")
307             {
308                 var nodeValue = context.Values[node] as EXamlCreateObject;
309
310                 if (nodeValue?.Instance is Xaml.Build.Tasks.ArrayExtension arrayExtension)
311                 {
312                     return arrayExtension.ProvideValue(node, module, context);
313                 }
314             }
315             else if (instance.GetType().ImplementsGenericInterface("Tizen.NUI.Xaml.IMarkupExtension`1", out markupExtension, out genericArguments))
316             {
317                 var nodeValue = context.Values[node] as EXamlCreateObject;
318                 if (nodeValue?.Instance is BindingExtension)
319                 {
320                     var newValue = (nodeValue.Instance as BindingExtension).ProvideValue(context, module);
321                     return newValue;
322                 }
323                 else if (nodeValue?.Instance is DynamicResourceExtension)
324                 {
325                     var dynamicResExtension = nodeValue.Instance as DynamicResourceExtension;
326                     var newValue = dynamicResExtension.ProvideValue();
327                     var newTypeRef = module.ImportReference(newValue.GetType());
328                     return new EXamlCreateObject(context, newValue, newTypeRef, new object[] { dynamicResExtension.Key });
329                 }
330             }
331             else
332             {
333                 var nodeValue = context.Values[node] as EXamlCreateObject;
334                 if (null != nodeValue)
335                 {
336                     if (nodeValue.GetType().ImplementsInterface(module.ImportReference((XamlTask.xamlAssemblyName, XamlTask.xamlNameSpace, "IMarkupExtension"))))
337                     {
338                         var acceptEmptyServiceProvider = instance.GetType().GetCustomAttribute(module, (XamlTask.xamlAssemblyName, XamlTask.xamlNameSpace, "AcceptEmptyServiceProviderAttribute")) != null;
339                         if (nodeValue.Instance is ReferenceExtension)
340                         {
341                             var newValue = (nodeValue.Instance as ReferenceExtension).ProvideValue(context);
342                             return newValue;
343                         }
344                         else if (nodeValue.Instance is StaticResourceExtension)
345                         {
346                             var newValue = (nodeValue.Instance as StaticResourceExtension).ProvideValue(context);
347                             return newValue;
348                         }
349                     }
350                     else if (nodeValue.GetType().ImplementsInterface(module.ImportReference((XamlTask.xamlAssemblyName, XamlTask.xamlNameSpace, "IValueProvider"))))
351                     {
352                         //var acceptEmptyServiceProvider = context.Variables[node].VariableType.GetCustomAttribute(module, (XamlCTask.xamlAssemblyName, XamlCTask.xamlNameSpace, "AcceptEmptyServiceProviderAttribute")) != null;
353                         //var valueProviderType = context.Variables[node].VariableType;
354                         ////If the IValueProvider has a ProvideCompiledAttribute that can be resolved, shortcut this
355                         //var compiledValueProviderName = valueProviderType?.GetCustomAttribute(module, (XamlCTask.xamlAssemblyName, XamlCTask.xamlNameSpace, "ProvideCompiledAttribute"))?.ConstructorArguments?[0].Value as string;
356                         //Type compiledValueProviderType;
357                         //if (compiledValueProviderName != null && (compiledValueProviderType = Type.GetType(compiledValueProviderName)) != null)
358                         //{
359                         //    var compiledValueProvider = Activator.CreateInstance(compiledValueProviderType);
360                         //    var cProvideValue = typeof(ICompiledValueProvider).GetMethods().FirstOrDefault(md => md.Name == "ProvideValue");
361                         //    var instructions = (IEnumerable<Instruction>)cProvideValue.Invoke(compiledValueProvider, new object[] {
362                         //instance,
363                         //context.Module,
364                         //node as BaseNode,
365                         //context});
366                         //foreach (var i in instructions)
367                         //    yield return i;
368                         //yield break;
369                         //}
370                     }
371                 }
372
373                 //instance.VariableDefinition = new VariableDefinition(module.TypeSystem.Object);
374                 //yield return Create(Ldloc, context.Variables[node]);
375                 //if (acceptEmptyServiceProvider)
376                 //    yield return Create(Ldnull);
377                 //else
378                 //    foreach (var instruction in node.PushServiceProvider(context, bpRef, propertyRef, propertyDeclaringTypeRef))
379                 //        yield return instruction;
380                 //yield return Create(Callvirt, module.ImportMethodReference((XamlCTask.xamlAssemblyName, XamlCTask.xamlNameSpace, "IValueProvider"),
381                 //                                                           methodName: "ProvideValue",
382                 //                                                           parameterTypes: new[] { ("System.ComponentModel", "System", "IServiceProvider") }));
383                 //yield return Create(Stloc, instance.VariableDefinition);
384             }
385
386             return null;
387         }
388
389         static IList<Tuple<PropertyDefinition, string>> ParsePath(string path, TypeReference tSourceRef, IXmlLineInfo lineInfo, ModuleDefinition module)
390         {
391             if (string.IsNullOrWhiteSpace(path))
392                 return null;
393             path = path.Trim(' ', '.'); //trim leading or trailing dots
394             var parts = path.Split(new [] { '.' }, StringSplitOptions.RemoveEmptyEntries);
395             var properties = new List<Tuple<PropertyDefinition, string>>();
396
397             var previousPartTypeRef = tSourceRef;
398             TypeReference _;
399             foreach (var part in parts) {
400                 var p = part;
401                 string indexArg = null;
402                 var lbIndex = p.IndexOf('[');
403                 if (lbIndex != -1) {
404                     var rbIndex = p.LastIndexOf(']');
405                     if (rbIndex == -1)
406                         throw new XamlParseException("Binding: Indexer did not contain closing bracket", lineInfo);
407                     
408                     var argLength = rbIndex - lbIndex - 1;
409                     if (argLength == 0)
410                         throw new XamlParseException("Binding: Indexer did not contain arguments", lineInfo);
411
412                     indexArg = p.Substring(lbIndex + 1, argLength).Trim();
413                     if (indexArg.Length == 0)
414                         throw new XamlParseException("Binding: Indexer did not contain arguments", lineInfo);
415                     
416                     p = p.Substring(0, lbIndex);
417                     p = p.Trim();
418                 }
419
420                 if (p.Length > 0) {
421                     var property = previousPartTypeRef.GetProperty(pd => pd.Name == p && pd.GetMethod != null && pd.GetMethod.IsPublic, out _)
422                                                       ?? throw new XamlParseException($"Binding: Property '{p}' not found on '{previousPartTypeRef}'", lineInfo);
423                     properties.Add(new Tuple<PropertyDefinition, string>(property,null));
424                     previousPartTypeRef = property.PropertyType;
425                 }
426                 if (indexArg != null) {
427                     var defaultMemberAttribute = previousPartTypeRef.GetCustomAttribute(module, ("mscorlib", "System.Reflection", "DefaultMemberAttribute"));
428                     var indexerName = defaultMemberAttribute?.ConstructorArguments?.FirstOrDefault().Value as string ?? "Item";
429                     var indexer = previousPartTypeRef.GetProperty(pd => pd.Name == indexerName && pd.GetMethod != null && pd.GetMethod.IsPublic, out _);
430                     properties.Add(new Tuple<PropertyDefinition, string>(indexer, indexArg));
431                     if (indexer.PropertyType != module.TypeSystem.String && indexer.PropertyType != module.TypeSystem.Int32)
432                         throw new XamlParseException($"Binding: Unsupported indexer index type: {indexer.PropertyType.FullName}", lineInfo);
433                     previousPartTypeRef = indexer.PropertyType;
434                 }
435             }
436             return properties;
437         }
438
439         public static void SetPropertyValue(EXamlCreateObject parent, XmlName propertyName, INode valueNode, EXamlContext context, IXmlLineInfo iXmlLineInfo)
440         {
441             var module = context.Module;
442             var localName = propertyName.LocalName;
443             bool attached;
444
445             var bpRef = GetBindablePropertyReference(parent, propertyName.NamespaceURI, ref localName, out attached, context, iXmlLineInfo);
446
447             //If the target is an event, connect
448             if (CanConnectEvent(parent, localName, attached))
449             {
450                 ConnectEvent(parent, localName, valueNode, iXmlLineInfo, context);
451             }
452             //If Value is DynamicResource, SetDynamicResource
453             else if (CanSetDynamicResource(bpRef, valueNode, context))
454             {
455                 SetDynamicResource(parent, bpRef, valueNode as IElementNode, iXmlLineInfo, context);
456             }
457             //If Value is a BindingBase and target is a BP, SetBinding
458             else if (CanSetBinding(bpRef, valueNode, context))
459             {
460                 SetBinding(parent, bpRef, valueNode as IElementNode, iXmlLineInfo, context);
461             }
462             //If it's a property, set it
463             else if (CanSet(parent, localName, valueNode, context))
464             {
465                 Set(parent, localName, valueNode, iXmlLineInfo, context);
466             }
467             //If it's a BP, SetValue ()
468             else if (CanSetValue(bpRef, attached, valueNode, iXmlLineInfo, context))
469             {
470                 SetValue(parent, bpRef, valueNode, iXmlLineInfo, context);
471             }
472             //If it's an already initialized property, add to it
473             else if (CanAdd(parent, propertyName, valueNode, iXmlLineInfo, context))
474             {
475                 Add(parent, localName, valueNode, iXmlLineInfo, context);
476             }
477             else
478             {
479                 throw new XamlParseException($"No property, bindable property, or event found for '{localName}', or mismatching type between value and property.", iXmlLineInfo);
480             }
481         }
482
483         //public static IEnumerable<Instruction> GetPropertyValue(EXamlCreateObject parent, XmlName propertyName, ILContext context, IXmlLineInfo lineInfo, out TypeReference propertyType)
484         //{
485         //    var module = context.Module;
486         //    var localName = propertyName.LocalName;
487         //    bool attached;
488         //    var bpRef = GetBindablePropertyReference(parent, propertyName.NamespaceURI, ref localName, out attached, context, lineInfo);
489
490         //    //If it's a BP, GetValue ()
491         //    if (CanGetValue(parent, bpRef, attached, lineInfo, context, out _))
492         //        return GetValue(parent, bpRef, lineInfo, context, out propertyType);
493
494         //    //If it's a property, set it
495         //    if (CanGet(parent, localName, context, out _))
496         //        return Get(parent, localName, lineInfo, context, out propertyType);
497
498         //    throw new XamlParseException($"Property {localName} is not found or does not have an accessible getter", lineInfo);
499         //}
500
501         static MemberReference GetBindablePropertyReference(EXamlCreateObject parent, string namespaceURI, ref string localName, out bool attached, EXamlContext context, IXmlLineInfo iXmlLineInfo)
502         {
503             var module = context.Module;
504             TypeReference declaringTypeReference;
505
506             //If it's an attached BP, update elementType and propertyName
507             var bpOwnerType = parent.GetType();
508             attached = GetNameAndTypeRef(ref bpOwnerType, namespaceURI, ref localName, context, iXmlLineInfo);
509             var name = $"{localName}Property";
510
511             PropertyReference prRef = bpOwnerType.GetProperty(p => p.Name == name &&
512                                                         p.GetMethod.IsStatic && p.GetMethod.IsPublic,
513                                                         out declaringTypeReference);
514
515             if (null != prRef)
516             {
517                 //prRef = module.ImportReference(prRef.ResolveGenericParameters(declaringTypeReference));
518                 prRef.PropertyType = module.ImportReference(prRef.PropertyType);
519                 return prRef;
520             }
521
522             FieldReference bpRef = bpOwnerType.GetField(fd => fd.Name == name &&
523                                                         fd.IsStatic &&
524                                                         (fd.IsPublic || fd.IsAssembly), out declaringTypeReference);
525             if (bpRef != null) {
526                 bpRef = module.ImportReference(bpRef.ResolveGenericParameters(declaringTypeReference));
527                 bpRef.FieldType = module.ImportReference(bpRef.FieldType);
528             }
529             return bpRef;
530         }
531
532         static bool CanConnectEvent(EXamlCreateObject parent, string localName, bool attached)
533         {
534             return !attached && parent.GetType().GetEvent(ed => ed.Name == localName, out _) != null;
535         }
536
537         static void ConnectEvent(EXamlCreateObject parent, string localName, INode valueNode, IXmlLineInfo iXmlLineInfo, EXamlContext context)
538         {
539             //Fang: Need to deal connect event
540             var elementType = parent.GetType();
541             var module = context.Module;
542             TypeReference eventDeclaringTypeRef;
543
544             var eventinfo = elementType.GetEvent(ed => ed.Name == localName, out eventDeclaringTypeRef);
545
546 //            IL_0007:  ldloc.0 
547 //            IL_0008:  ldarg.0 
548 //
549 //            IL_0009:  ldftn instance void class Tizen.NUI.Xaml.XamlcTests.MyPage::OnButtonClicked(object, class [mscorlib]System.EventArgs)
550 //OR, if the handler is virtual
551 //            IL_000x:  ldarg.0 
552 //            IL_0009:  ldvirtftn instance void class Tizen.NUI.Xaml.XamlcTests.MyPage::OnButtonClicked(object, class [mscorlib]System.EventArgs)
553 //
554 //            IL_000f:  newobj instance void class [mscorlib]System.EventHandler::'.ctor'(object, native int)
555 //            IL_0014:  callvirt instance void class [Tizen.NUI.Xaml.Core]Tizen.NUI.Xaml.Button::add_Clicked(class [mscorlib]System.EventHandler)
556
557             var value = ((ValueNode)valueNode).Value;
558
559             //if (context.Root is VariableDefinition)
560             //    yield return Create(Ldloc, context.Root as VariableDefinition);
561             //else if (context.Root is FieldDefinition)
562             //{
563             //    yield return Create(Ldarg_0);
564             //    yield return Create(Ldfld, context.Root as FieldDefinition);
565             //}
566             //else
567             //    throw new InvalidProgramException();
568             var declaringType = context.Type;
569             while (declaringType.IsNested)
570                 declaringType = declaringType.DeclaringType;
571             var handler = declaringType.AllMethods().FirstOrDefault(md => md.Name == value as string);
572
573             //check if the handler signature matches the Invoke signature;
574             var invoke = module.ImportReference(eventinfo.EventType.ResolveCached().GetMethods().First(md => md.Name == "Invoke"));
575             invoke = invoke.ResolveGenericParameters(eventinfo.EventType, module);
576             if (!handler.ReturnType.InheritsFromOrImplements(invoke.ReturnType))
577             {
578                 TypeDefinition realType = eventinfo.EventType.ResolveCached();
579
580                 GenericInstanceType genericInstanceType = eventinfo.EventType as GenericInstanceType;
581
582                 if (null != genericInstanceType
583                     && genericInstanceType.GenericArguments.Count == realType.GenericParameters.Count)
584                 {
585                     Dictionary<string, TypeReference> dict = new Dictionary<string, TypeReference>();
586
587                     for (int i = 0; i < realType.GenericParameters.Count; i++)
588                     {
589                         string p = realType.GenericParameters[i].Name;
590                         TypeReference type = genericInstanceType.GenericArguments[i];
591
592                         dict.Add(p, type);
593                     }
594
595                     if (dict.ContainsKey(invoke.ReturnType.Name))
596                     {
597                         invoke.ReturnType = dict[invoke.ReturnType.Name];
598                     }
599
600                     for (int i = 0; i < invoke.Parameters.Count; i++)
601                     {
602                         if (dict.ContainsKey(invoke.Parameters[i].ParameterType.Name))
603                         {
604                             invoke.Parameters[i].ParameterType = dict[invoke.Parameters[i].ParameterType.Name];
605                         }
606                     }
607                 }
608             }
609
610             if (!handler.ReturnType.InheritsFromOrImplements(invoke.ReturnType))
611                 throw new XamlParseException($"Signature (return type) of EventHandler \"{context.Type.FullName}.{value}\" doesn't match the event type", iXmlLineInfo);
612             if (invoke.Parameters.Count != handler.Parameters.Count)
613                 throw new XamlParseException($"Signature (number of arguments) of EventHandler \"{context.Type.FullName}.{value}\" doesn't match the event type", iXmlLineInfo);
614             if (!invoke.ContainsGenericParameter)
615                 for (var i = 0; i < invoke.Parameters.Count; i++)
616                     if (!handler.Parameters[i].ParameterType.InheritsFromOrImplements(invoke.Parameters[i].ParameterType))
617                         throw new XamlParseException($"Signature (parameter {i}) of EventHandler \"{context.Type.FullName}.{value}\" doesn't match the event type", iXmlLineInfo);
618
619             new EXamlAddEvent(context, parent, context.Values[context.RootNode] as EXamlCreateObject, localName, handler);
620         }
621
622         static bool CanSetDynamicResource(MemberReference bpRef, INode valueNode, EXamlContext context)
623         {
624             if (bpRef == null)
625                 return false;
626             var elementNode = valueNode as IElementNode;
627             if (elementNode == null)
628                 return false;
629
630             var valueInstance = context.Values[valueNode] as EXamlCreateObject;
631             if (null == valueInstance)
632                 return false;
633
634             return valueInstance.GetType().FullName == typeof(DynamicResource).FullName;
635         }
636
637         static void SetDynamicResource(EXamlCreateObject parent, MemberReference bpRef, IElementNode elementNode, IXmlLineInfo iXmlLineInfo, EXamlContext context)
638         {
639             var instance = context.Values[elementNode] as EXamlCreateObject;
640             if (null != instance)
641             {
642                 var dynamicResource = instance.Instance as DynamicResource;
643
644                 if (null != dynamicResource)
645                 {
646                     instance.IsValid = false;
647                     new EXamlSetDynamicResource(context, parent, bpRef, dynamicResource.Key);
648                 }
649             }
650         }
651
652         static bool CanSetBinding(MemberReference bpRef, INode valueNode, EXamlContext context)
653         {
654             var module = context.Module;
655
656             if (bpRef == null)
657                 return false;
658             var elementNode = valueNode as IElementNode;
659             if (elementNode == null)
660                 return false;
661
662             var valueInstance = context.Values[valueNode] as EXamlCreateObject;
663             if (null == valueInstance)
664                 return false;
665
666             var implicitOperator = valueInstance.GetType().GetImplicitOperatorTo(module.ImportReference((XamlTask.bindingAssemblyName, XamlTask.bindingNameSpace, "BindingBase")), module);
667             if (implicitOperator != null)
668                 return true;
669
670             return valueInstance.GetType().InheritsFromOrImplements(XamlTask.bindingNameSpace + ".BindingBase");
671         }
672
673         static void SetBinding(EXamlCreateObject parent, MemberReference bpRef, IElementNode elementNode, IXmlLineInfo iXmlLineInfo, EXamlContext context)
674         {
675             new EXamlSetBinding(context, parent, bpRef, context.Values[elementNode]);
676         }
677
678         static bool CanSetValue(MemberReference bpRef, bool attached, INode node, IXmlLineInfo iXmlLineInfo, EXamlContext context)
679         {
680             var module = context.Module;
681
682             if (bpRef == null)
683                 return false;
684
685             var valueNode = node as ValueNode;
686             if (valueNode != null && valueNode.CanConvertValue(context.Module, bpRef))
687                 return true;
688
689             var elementNode = node as IElementNode;
690             if (elementNode == null)
691                 return false;
692
693             return context.Values.ContainsKey(elementNode);
694
695             //VariableDefinition varValue;
696             //if (!context.Variables.TryGetValue(elementNode, out varValue))
697             //    return false;
698
699    //         var bpTypeRef = bpRef.GetBindablePropertyType(iXmlLineInfo, module);
700             //// If it's an attached BP, there's no second chance to handle IMarkupExtensions, so we try here.
701             //// Worst case scenario ? InvalidCastException at runtime
702             //if (attached && varValue.VariableType.FullName == "System.Object") 
703             //    return true;
704             //var implicitOperator = varValue.VariableType.GetImplicitOperatorTo(bpTypeRef, module);
705             //if (implicitOperator != null)
706             //    return true;
707
708             ////as we're in the SetValue Scenario, we can accept value types, they'll be boxed
709             //if (varValue.VariableType.IsValueType && bpTypeRef.FullName == "System.Object")
710             //    return true;
711
712             //return varValue.VariableType.InheritsFromOrImplements(bpTypeRef);
713         }
714
715         static bool CanGetValue(EXamlCreateObject parent, MemberReference bpRef, bool attached, IXmlLineInfo iXmlLineInfo, EXamlContext context, out TypeReference propertyType)
716         {
717             var module = context.Module;
718             propertyType = null;
719
720             if (bpRef == null)
721                 return false;
722
723             if (!parent.GetType().InheritsFromOrImplements(module.ImportReference((XamlTask.bindingAssemblyName, XamlTask.bindingNameSpace, "BindableObject"))))
724                 return false;
725
726             propertyType = bpRef.GetBindablePropertyType(iXmlLineInfo, module);
727             return true;
728         }
729
730         static void SetValue(EXamlCreateObject parent, MemberReference bpRef, INode node, IXmlLineInfo iXmlLineInfo, EXamlContext context)
731         {
732             var valueNode = node as ValueNode;
733
734             if (valueNode != null)
735             {
736                 var valueType = bpRef.GetBindablePropertyType(null, context.Module);
737                 var converterType = valueNode.GetConverterType(new ICustomAttributeProvider[] { valueType.Resolve() });
738                 if (null != converterType)
739                 {
740                     var converterValue = new EXamlValueConverterFromString(context, converterType.Resolve(), valueNode.Value as string);
741                     context.Values[node] = new EXamlCreateObject(context, converterValue, valueType);
742                 }
743                 else
744                 {
745                     context.Values[node] = valueNode.GetBaseValue(context, valueType);
746                 }
747             }
748
749             new EXamlSetBindalbeProperty(context, parent, bpRef, context.Values[node]);
750         }
751
752         static void GetValue(EXamlCreateObject parent, FieldReference bpRef, IXmlLineInfo iXmlLineInfo, EXamlContext context, out TypeReference propertyType)
753         {
754             var module = context.Module;
755             propertyType = bpRef.GetBindablePropertyType(iXmlLineInfo, module);
756
757             //return new[] {
758             //    Create(Ldloc, parent),
759             //    Create(Ldsfld, bpRef),
760             //    Create(Callvirt,  module.ImportMethodReference((XamlCTask.bindingAssemblyName, XamlCTask.bindingNameSpace, "BindableObject"),
761             //                                                   methodName: "GetValue",
762             //                                                   parameterTypes: new[] { (XamlCTask.bindingAssemblyName, XamlCTask.bindingNameSpace, "BindableProperty") })),
763             //};
764         }
765
766         static bool CanSet(EXamlCreateObject parent, string localName, INode node, EXamlContext context)
767         {
768             var module = context.Module;
769             TypeReference declaringTypeReference;
770             var property = parent.GetType().GetProperty(pd => pd.Name == localName, out declaringTypeReference);
771             if (property == null)
772                 return false;
773             var propertyType = property.ResolveGenericPropertyType(declaringTypeReference, module);
774             var propertySetter = property.SetMethod;
775             if (propertySetter == null || !propertySetter.IsPublic || propertySetter.IsStatic)
776                 return false;
777
778             var valueNode = node as ValueNode;
779             if (valueNode != null && valueNode.CanConvertValue(context.Module, propertyType, new ICustomAttributeProvider[] { property, propertyType.ResolveCached()}))
780                 return true;
781
782             var elementNode = node as IElementNode;
783             if (elementNode == null)
784                 return false;
785
786             var vardef = context.Variables[elementNode];
787             var implicitOperator = vardef.VariableType.GetImplicitOperatorTo(propertyType, module);
788
789             var value = context.Values[elementNode] as EXamlCreateObject;
790
791             if (vardef.VariableType.InheritsFromOrImplements(propertyType))
792                 return true;
793             if (null != value && value.GetType().InheritsFromOrImplements(propertyType))
794                 return true;
795             if (implicitOperator != null)
796                 return true;
797             if (propertyType.FullName == "System.Object")
798                 return true;
799
800             //I'd like to get rid of this condition. This comment used to be //TODO replace latest check by a runtime type check
801             if (vardef.VariableType.FullName == "System.Object")
802                 return true;
803
804             var realValue = context.Values[elementNode] as EXamlCreateObject;
805             if (null != realValue)
806             {
807                 var valueTypeRef = realValue.GetType();
808                 if (valueTypeRef.InheritsFromOrImplements(propertyType))
809                 {
810                     return true;
811                 }
812
813                 var realTypeFromMarkupExtension = valueTypeRef.GetRealTypeIfIsMarkupExtension();
814
815                 if (true == realTypeFromMarkupExtension?.InheritsFromOrImplements(propertyType))
816                 {
817                     return true;
818                 }
819             }
820
821             return false;
822         }
823
824         static bool CanGet(EXamlCreateObject parent, string localName, EXamlContext context, out TypeReference propertyType)
825         {
826             var module = context.Module;
827             propertyType = null;
828             TypeReference declaringTypeReference;
829             var property = parent.GetType().GetProperty(pd => pd.Name == localName, out declaringTypeReference);
830             if (property == null)
831                 return false;
832             var propertyGetter = property.GetMethod;
833             if (propertyGetter == null || !propertyGetter.IsPublic || propertyGetter.IsStatic)
834                 return false;
835
836             module.ImportReference(parent.GetType().ResolveCached());
837             var propertyGetterRef = module.ImportReference(module.ImportReference(propertyGetter).ResolveGenericParameters(declaringTypeReference, module));
838             propertyGetterRef.ImportTypes(module);
839             propertyType = propertyGetterRef.ReturnType.ResolveGenericParameters(declaringTypeReference);
840
841             return true;
842         }
843
844         static void Set(EXamlCreateObject parent, string localName, INode node, IXmlLineInfo iXmlLineInfo, EXamlContext context)
845         {
846             var module = context.Module;
847             TypeReference declaringTypeReference;
848             var property = parent.Type.GetProperty(pd => pd.Name == localName, out declaringTypeReference);
849             var propertySetter = property.SetMethod;
850
851             ////            IL_0007:  ldloc.0
852             ////            IL_0008:  ldstr "foo"
853             ////            IL_000d:  callvirt instance void class [Tizen.NUI.Xaml.Core]Tizen.NUI.Xaml.Label::set_Text(string)
854
855             var propertySetterRef = module.ImportReference(module.ImportReference(propertySetter).ResolveGenericParameters(declaringTypeReference, module));
856             propertySetterRef.ImportTypes(module);
857             var propertyType = property.ResolveGenericPropertyType(declaringTypeReference, module);
858             var valueNode = node as ValueNode;
859             var elementNode = node as IElementNode;
860
861             //if it's a value type, load the address so we can invoke methods on it
862             if (parent.Type.IsValueType)
863             {
864             //    yield return Instruction.Create(OpCodes.Ldloca, parent);
865             }
866             else
867             {
868             //    yield return Instruction.Create(OpCodes.Ldloc, parent);
869             }
870
871             if (valueNode != null)
872             {
873                 if ("Tizen.NUI.Binding.BindableProperty" == propertyType.FullName)
874                 {
875                     var bindableProperty = BindablePropertyConverter.GetBindablePropertyFieldReference(valueNode.Value as string, module, node as BaseNode);
876                     var fieldRef = bindableProperty.DeclaringType.ResolveCached().Fields.FirstOrDefault(a => a.FullName == bindableProperty.FullName);
877                     context.Values[node] = new EXamlCreateObject(context, bindableProperty.DeclaringType, fieldRef, null);
878                 }
879                 else
880                 {
881                     var converterType = valueNode.GetConverterType(new ICustomAttributeProvider[] { property, propertyType.ResolveCached() });
882                     if (null != converterType)
883                     {
884                         var converterValue = new EXamlValueConverterFromString(context, converterType.Resolve(), valueNode.Value as string);
885                         context.Values[node] = new EXamlCreateObject(context, converterValue, propertyType);
886                     }
887                     else
888                     {
889                         context.Values[node] = valueNode.GetBaseValue(context, property.PropertyType);
890                     }
891                 }
892             }
893             else if (elementNode != null)
894             {
895                 var vardef = context.Variables[elementNode];
896                 var implicitOperator = vardef.VariableType.GetImplicitOperatorTo(propertyType, module);
897                 //yield return Instruction.Create(OpCodes.Ldloc, vardef);
898                 if (!vardef.VariableType.InheritsFromOrImplements(propertyType) && implicitOperator != null)
899                 {
900                     //                    IL_000f:  call !0 class [Tizen.NUI.Xaml.Core]Tizen.NUI.Xaml.OnPlatform`1<bool>::op_Implicit(class [Tizen.NUI.Xaml.Core]Tizen.NUI.Xaml.OnPlatform`1<!0>)
901                     //yield return Instruction.Create(OpCodes.Call, module.ImportReference(implicitOperator));
902                 }
903                 else if (!vardef.VariableType.IsValueType && propertyType.IsValueType)
904                 {
905                     //yield return Instruction.Create(OpCodes.Unbox_Any, module.ImportReference(propertyType));
906                 }
907                 else if (vardef.VariableType.IsValueType && propertyType.FullName == "System.Object")
908                 {
909                     //yield return Instruction.Create(OpCodes.Box, vardef.VariableType);
910                 }
911                 if (parent.Type.IsValueType)
912                 {
913                     //yield return Instruction.Create(OpCodes.Call, propertySetterRef);
914                 }
915                 else
916                 {
917                     //yield return Instruction.Create(OpCodes.Callvirt, propertySetterRef);
918                 }
919             }
920
921             new EXamlSetProperty(context, parent, localName, context.Values[node]);
922         }
923
924         static void Get(EXamlCreateObject parent, string localName, IXmlLineInfo iXmlLineInfo, EXamlContext context, out TypeReference propertyType)
925         {
926             var module = context.Module;
927             var property = parent.GetType().GetProperty(pd => pd.Name == localName, out var declaringTypeReference);
928             var propertyGetter = property.GetMethod;
929
930             module.ImportReference(parent.GetType().ResolveCached());
931             var propertyGetterRef = module.ImportReference(module.ImportReference(propertyGetter).ResolveGenericParameters(declaringTypeReference, module));
932             propertyGetterRef.ImportTypes(module);
933             propertyType = propertyGetterRef.ReturnType.ResolveGenericParameters(declaringTypeReference);
934
935             //if (parent.VariableType.IsValueType)
936             //    return new[] {
937             //        Instruction.Create(OpCodes.Ldloca, parent),
938             //        Instruction.Create(OpCodes.Call, propertyGetterRef),
939             //    };
940             //else
941             //    return new[] {
942             //        Instruction.Create(OpCodes.Ldloc, parent),
943             //        Instruction.Create(OpCodes.Callvirt, propertyGetterRef),
944             //    };
945         }
946
947         static bool CanAdd(EXamlCreateObject parent, XmlName propertyName, INode node, IXmlLineInfo lineInfo, EXamlContext context)
948         {
949             var module = context.Module;
950             var localName = propertyName.LocalName;
951             bool attached;
952             var bpRef = GetBindablePropertyReference(parent, propertyName.NamespaceURI, ref localName, out attached, context, lineInfo);
953             TypeReference propertyType;
954
955             if (   !CanGetValue(parent, bpRef, attached, null, context, out propertyType)
956                 && !CanGet(parent, localName, context, out propertyType))
957                 return false;
958
959             //TODO check md.Parameters[0] type
960             var adderTuple = propertyType.GetMethods(md => md.Name == "Add" && md.Parameters.Count == 1, module).FirstOrDefault();
961             if (adderTuple == null)
962                 return false;
963
964             return true;
965         }
966
967         static Dictionary<EXamlCreateObject, IList<string>> resourceNamesInUse = new Dictionary<EXamlCreateObject, IList<string>>();
968         static bool CanAddToResourceDictionary(EXamlCreateObject parent, TypeReference collectionType, IElementNode node, IXmlLineInfo lineInfo, EXamlContext context)
969         {
970             if (   collectionType.FullName != "Tizen.NUI.Binding.ResourceDictionary"
971                 && collectionType.ResolveCached().BaseType?.FullName != "Tizen.NUI.Binding.ResourceDictionary")
972                 return false;
973
974
975             if (node.Properties.ContainsKey(XmlName.xKey)) {
976                 var key = (node.Properties[XmlName.xKey] as ValueNode).Value as string;
977                 if (!resourceNamesInUse.TryGetValue(parent, out var names))
978                     resourceNamesInUse[parent] = (names = new List<string>());
979                 if (names.Contains(key))
980                     throw new XamlParseException($"A resource with the key '{key}' is already present in the ResourceDictionary.", lineInfo);
981                 names.Add(key);
982                 return true;
983             }
984
985             //is there a RD.Add() overrides that accepts this ?
986             var nodeTypeRef = context.Variables[node].VariableType;
987             var module = context.Module;
988             if (module.ImportMethodReference((XamlTask.bindingAssemblyName, XamlTask.bindingNameSpace, "ResourceDictionary"),
989                                              methodName: "Add",
990                                              parameterTypes: new[] { (nodeTypeRef.Scope.Name, nodeTypeRef.Namespace, nodeTypeRef.Name) }) != null)
991                 return true;
992
993             throw new XamlParseException("resources in ResourceDictionary require a x:Key attribute", lineInfo);
994         }
995
996         static void Add(EXamlCreateObject parent, string propertyName, INode node, IXmlLineInfo iXmlLineInfo, EXamlContext context)
997         {
998             //Fang: Need to deal
999             var module = context.Module;
1000             var elementNode = node as IElementNode;
1001
1002             TypeReference declaringTypeReference;
1003             var property = parent.Type.GetProperty(pd => pd.Name == propertyName, out declaringTypeReference);
1004             TypeReference propertyType = property.PropertyType;
1005
1006             if (null != elementNode && CanAddToResourceDictionary(parent, propertyType, elementNode, iXmlLineInfo, context))
1007             {
1008                 var keyName = (elementNode.Properties[XmlName.xKey] as ValueNode).Value as string;
1009                 new EXamlAddToResourceDictionary(context, parent, keyName, context.Values[node]);
1010                 return;
1011             }
1012
1013             var adderTuple = propertyType.GetMethods(md => md.Name == "Add" && md.Parameters.Count == 1, module).FirstOrDefault();
1014             var adderRef = module.ImportReference(adderTuple.Item1);
1015             adderRef = module.ImportReference(adderRef.ResolveGenericParameters(adderTuple.Item2, module));
1016             var childType = GetParameterType(adderRef.Parameters[0]);
1017
1018             if (node is ValueNode valueNode)
1019             {
1020                 if (true == valueNode.CanConvertValue(module, childType, (TypeReference)null))
1021                 {
1022                     var obj = new EXamlGetObjectByProperty(context, parent, propertyName);
1023
1024                     var converterType = valueNode.GetConverterType(new ICustomAttributeProvider[] { property, childType.ResolveCached() });
1025                     if (null != converterType)
1026                     {
1027                         var converterValue = new EXamlValueConverterFromString(context, converterType.Resolve(), valueNode.Value as string);
1028                         context.Values[node] = new EXamlCreateObject(context, converterValue, propertyType);
1029                     }
1030                     else
1031                     {
1032                         context.Values[node] = valueNode.GetBaseValue(context, childType);
1033                     }
1034                     new EXamlAddToCollectionProperty(context, obj, context.Values[node]);
1035                 }
1036             }
1037             else if (node is ElementNode element)
1038             {
1039                 var obj = new EXamlGetObjectByProperty(context, parent, propertyName);
1040                 new EXamlAddToCollectionProperty(context, obj, context.Values[node]);
1041             }
1042         }
1043
1044         static IEnumerable<Instruction> AddToResourceDictionary(IElementNode node, IXmlLineInfo lineInfo, EXamlContext context)
1045         {
1046             var module = context.Module;
1047
1048             if (node.Properties.ContainsKey(XmlName.xKey)) {
1049 //                IL_0014:  ldstr "key"
1050 //                IL_0019:  ldstr "foo"
1051 //                IL_001e:  callvirt instance void class [Tizen.NUI.Xaml.Core]Tizen.NUI.Xaml.ResourceDictionary::Add(string, object)
1052                 yield return Create(Ldstr, (node.Properties[XmlName.xKey] as ValueNode).Value as string);
1053                 var varDef = context.Variables[node];
1054                 yield return Create(Ldloc, varDef);
1055                 if (varDef.VariableType.IsValueType)
1056                     yield return Create(Box, module.ImportReference(varDef.VariableType));
1057                 yield return Create(Callvirt, module.ImportMethodReference((XamlTask.bindingAssemblyName, XamlTask.bindingNameSpace, "ResourceDictionary"),
1058                                                                            methodName: "Add",
1059                                                                            parameterTypes: new[] {
1060                                                                                ("mscorlib", "System", "String"),
1061                                                                                ("mscorlib", "System", "Object"),
1062                                                                            }));
1063                 yield break;
1064             }
1065
1066             var nodeTypeRef = context.Variables[node].VariableType;
1067             yield return Create(Ldloc, context.Variables[node]);
1068             yield return Create(Callvirt, module.ImportMethodReference((XamlTask.bindingAssemblyName, XamlTask.bindingNameSpace, "ResourceDictionary"),
1069                                                                        methodName: "Add",
1070                                                                        parameterTypes: new[] { (nodeTypeRef.Scope.Name, nodeTypeRef.Namespace, nodeTypeRef.Name) }));
1071             yield break;
1072         }
1073
1074         public static TypeReference GetParameterType(ParameterDefinition param)
1075         {
1076             if (!param.ParameterType.IsGenericParameter)
1077                 return param.ParameterType;
1078             var type = (param.Method as MethodReference).DeclaringType as GenericInstanceType;
1079             return type.GenericArguments [0];
1080         }
1081
1082         static bool GetNameAndTypeRef(ref TypeReference elementType, string namespaceURI, ref string localname,
1083             EXamlContext context, IXmlLineInfo lineInfo)
1084         {
1085             var dotIdx = localname.IndexOf('.');
1086             if (dotIdx > 0)
1087             {
1088                 var typename = localname.Substring(0, dotIdx);
1089                 localname = localname.Substring(dotIdx + 1);
1090                 elementType = new XmlType(namespaceURI, typename, null).GetTypeReference(context.Module, lineInfo);
1091                 return true;
1092             }
1093             return false;
1094         }
1095
1096         static void SetDataTemplate(ElementNode parentNode, ElementNode rootnode, EXamlContext parentContext,
1097             IXmlLineInfo xmlLineInfo)
1098         {
1099             var typeref = parentContext.Module.ImportReference(rootnode.XmlType.GetTypeReference(parentContext.Module, rootnode));
1100             var visitorContext = new EXamlContext(typeref.ResolveCached(), typeref.Module);
1101
1102             rootnode.Accept(new XamlNodeVisitor((node, parent) => node.Parent = parent), null);
1103             rootnode.Accept(new EXamlExpandMarkupsVisitor(visitorContext), null);
1104             rootnode.Accept(new PruneIgnoredNodesVisitor(), null);
1105             rootnode.Accept(new EXamlCreateObjectVisitor(visitorContext), null);
1106             rootnode.Accept(new EXamlSetNamescopesAndRegisterNamesVisitor(visitorContext), null);
1107             rootnode.Accept(new EXamlSetFieldVisitor(visitorContext), null);
1108             rootnode.Accept(new EXamlSetResourcesVisitor(visitorContext), null);
1109             rootnode.Accept(new EXamlSetPropertiesVisitor(visitorContext, true), null);
1110
1111             var eXamlString = visitorContext.GenerateEXamlString();
1112
1113             var parentTyperef = parentContext.Module.ImportReference(parentNode.XmlType.GetTypeReference(parentContext.Module, parentNode));
1114
1115             if (parentContext.Values[parentNode] is EXamlCreateObject eXamlObject)
1116             {
1117                 eXamlObject.IsValid = false;
1118                 parentContext.Values[parentNode] = new EXamlCreateDataTemplate(parentContext, parentTyperef, eXamlString);
1119             }
1120         }
1121
1122         bool TrySetRuntimeName(XmlName propertyName, EXamlCreateObject variableDefinition, ValueNode node)
1123         {
1124             if (null == variableDefinition)
1125             {
1126                 return false;
1127             }
1128
1129             if (propertyName != XmlName.xName)
1130                 return false;
1131
1132             var attributes = variableDefinition.GetType().ResolveCached()
1133                 .CustomAttributes.Where(attribute => attribute.AttributeType.FullName == "Tizen.NUI.Xaml.RuntimeNamePropertyAttribute").ToList();
1134
1135             if (!attributes.Any())
1136                 return false;
1137
1138             var runTimeName = attributes[0].ConstructorArguments[0].Value as string;
1139
1140             if (string.IsNullOrEmpty(runTimeName)) 
1141                 return false;
1142
1143             SetPropertyValue(variableDefinition, new XmlName("", runTimeName), node, Context, node);
1144             return true;
1145         }
1146     }
1147 }
1148