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