[NUI][Xaml] Support Dictionary which has string key in Xaml
authorFang Xiaohui <xiaohui.fang@samsung.com>
Thu, 2 Jun 2022 08:43:36 +0000 (16:43 +0800)
committerdongsug-song <35130733+dongsug-song@users.noreply.github.com>
Thu, 2 Jun 2022 08:52:01 +0000 (17:52 +0900)
pkg/Tizen.NET.API9/xamlbuild/Tizen.NUI.XamlBuild.dll
src/Tizen.NUI.XamlBuild/src/public/XamlBuild/SetPropertiesVisitor.cs
src/Tizen.NUI.XamlBuild/src/public/XamlBuild/TypeReferenceExtensions.cs

index 064c496..e54e2f7 100644 (file)
Binary files a/pkg/Tizen.NET.API9/xamlbuild/Tizen.NUI.XamlBuild.dll and b/pkg/Tizen.NET.API9/xamlbuild/Tizen.NUI.XamlBuild.dll differ
index 4bfc9cf..8d91d71 100755 (executable)
@@ -166,6 +166,12 @@ namespace Tizen.NUI.Xaml.Build.Tasks
                     Context.IL.Append(AddToResourceDictionary(node, node, Context));
                     isAdded = true;
                 }
+                else if (CanAddToDictionary(parentVar, parentVar.VariableType, node, node, Context))
+                {
+                    Context.IL.Emit(Ldloc, parentVar);
+                    Context.IL.Append(AddToDictionary(node, parentVar, node, Context));
+                    isAdded = true;
+                }
                 // Collection element, implicit content, or implicit collection element.
                 else if (parentVar.VariableType.GetMethods(md => md.Name == "Add" && md.Parameters.Count == 1, Module).Any())
                 {
@@ -1347,6 +1353,31 @@ namespace Tizen.NUI.Xaml.Build.Tasks
             throw new XamlParseException("resources in ResourceDictionary require a x:Key attribute", lineInfo);
         }
 
+        static bool CanAddToDictionary(VariableDefinition parent, TypeReference collectionType, IElementNode node, IXmlLineInfo lineInfo, ILContext context)
+        {
+            var typeOfDictionary = collectionType.GetRealTypeOfDictionary();
+
+            if (null != typeOfDictionary)
+            {
+                if ("System.String" == typeOfDictionary.GenericArguments[0].FullName)
+                {
+                    if (node.Properties.ContainsKey(XmlName.xKey))
+                    {
+                        var valueType = node.XmlType.GetTypeReference(XmlTypeExtensions.ModeOfGetType.OnlyGetType, parent.VariableType.Module, lineInfo);
+
+                        if ("System.Object" == typeOfDictionary.GenericArguments[1].FullName
+                            ||
+                            valueType.InheritsFromOrImplements(typeOfDictionary.GenericArguments[1]))
+                        {
+                            return true;
+                        }
+                    }
+                }
+            }
+
+            return false;
+        }
+
         static IEnumerable<Instruction> Add(VariableDefinition parent, XmlName propertyName, INode node, IXmlLineInfo iXmlLineInfo, ILContext context)
         {
             var module = context.Body.Method.Module;
@@ -1409,6 +1440,49 @@ namespace Tizen.NUI.Xaml.Build.Tasks
             yield break;
         }
 
+        static IEnumerable<Instruction> AddToDictionary(IElementNode node, VariableDefinition parent, IXmlLineInfo lineInfo, ILContext context)
+        {
+            var module = context.Body.Method.Module;
+
+            if (node.Properties.ContainsKey(XmlName.xKey))
+            {
+                yield return Create(Ldstr, (node.Properties[XmlName.xKey] as ValueNode).Value as string);
+                var varDef = context.Variables[node];
+                yield return Create(Ldloc, varDef);
+                if (varDef.VariableType.IsValueType)
+                    yield return Create(Box, module.ImportReference(varDef.VariableType));
+
+                MethodReference addMethod = null;
+
+                foreach (var methodTuple in parent.VariableType.GetMethods(m => m.Name == "Add", module))
+                {
+                    var method = methodTuple.Item1;
+                    var typeOfMethod = methodTuple.Item2 as GenericInstanceType;
+
+                    if (null != typeOfMethod && "System.Collections.Generic.Dictionary`2" == typeOfMethod.ElementType.FullName)
+                    {
+                        var realMethod = new MethodReference("Add", method.ReturnType);
+                        realMethod.DeclaringType = typeOfMethod;
+                        realMethod.CallingConvention = method.CallingConvention;
+                        realMethod.ExplicitThis = method.ExplicitThis;
+                        realMethod.HasThis = method.HasThis;
+                        realMethod.Parameters.Add(method.Parameters[0]);
+                        realMethod.Parameters.Add(method.Parameters[1]);
+
+                        addMethod = module.ImportReference(realMethod);
+                        break;
+                    }
+                }
+
+                if (null != addMethod)
+                {
+                    yield return Create(Callvirt, addMethod);
+                }
+
+                yield break;
+            }
+        }
+
         public static TypeReference GetParameterType(ParameterDefinition param)
         {
             if (!param.ParameterType.IsGenericParameter)
index d0a3b24..d36fa7b 100755 (executable)
@@ -489,6 +489,25 @@ namespace Tizen.NUI.Xaml.Build.Tasks
             return false;
         }
 
+        public static GenericInstanceType GetRealTypeOfDictionary(this TypeReference typeReference)
+        {
+            if (null == typeReference)
+            {
+                return null;
+            }
+
+            if (typeReference is GenericInstanceType instanceType
+                &&
+                "System.Collections.Generic.Dictionary`2" == instanceType.ElementType.FullName)
+            {
+                return instanceType;
+            }
+
+            var baseType = typeReference.ResolveCached()?.BaseType;
+
+            return GetRealTypeOfDictionary(baseType);
+        }
+
         static Dictionary<TypeReference, TypeDefinition> resolves = new Dictionary<TypeReference, TypeDefinition>();
         public static TypeDefinition ResolveCached(this TypeReference typeReference)
         {