[NUI] Support factory method in EXaml
authorFang Xiaohui <xiaohui.fang@samsung.com>
Fri, 4 Jun 2021 08:16:21 +0000 (16:16 +0800)
committerdongsug-song <35130733+dongsug-song@users.noreply.github.com>
Wed, 9 Jun 2021 03:12:19 +0000 (12:12 +0900)
src/Tizen.NUI/src/internal/EXaml/Action/CreateInstanceAction.cs
src/Tizen.NUI/src/internal/EXaml/Block/GatherMethodsBlock.cs
src/Tizen.NUI/src/internal/EXaml/Operation/CreateInstance.cs
src/Tizen.NUI/src/internal/EXaml/Operation/GatherMethod.cs
src/Tizen.NUI/src/internal/EXaml/Utility/GetBaseType.cs [new file with mode: 0755]

index bd45af1..19e4f12 100755 (executable)
@@ -50,6 +50,10 @@ namespace Tizen.NUI.EXaml
                     getParamListOp = new GetValueListAction(')', this);
                     return getParamListOp;
 
+                case '[':
+                    getXFactoryMethodIndexOp = new GetValueListAction(']', this);
+                    return getXFactoryMethodIndexOp;
+
                 default:
                     getTypeIndexOp = new GetValueAction(c, this);
                     return getTypeIndexOp;
@@ -67,13 +71,15 @@ namespace Tizen.NUI.EXaml
             if (null != getTypeIndexOp)
             {
                 int typeIndex = (int)getTypeIndexOp.Value;
+                int xFactoryMethodIndex = (null == getXFactoryMethodIndexOp) ? -1 : (int)getXFactoryMethodIndexOp.ValueList[0];
+
                 if (null == getParamListOp)
                 {
-                    globalDataList.Operations.Add(new CreateInstance(globalDataList, typeIndex));
+                    globalDataList.Operations.Add(new CreateInstance(globalDataList, typeIndex, xFactoryMethodIndex));
                 }
                 else
                 {
-                    globalDataList.Operations.Add(new CreateInstance(globalDataList, typeIndex, getParamListOp.ValueList));
+                    globalDataList.Operations.Add(new CreateInstance(globalDataList, typeIndex, xFactoryMethodIndex, getParamListOp.ValueList));
                 }
                 getParamListOp = null;
             }
@@ -82,6 +88,7 @@ namespace Tizen.NUI.EXaml
         }
 
         private GetValueAction getTypeIndexOp;
+        private GetValueListAction getXFactoryMethodIndexOp;
         private GetValueListAction getParamListOp;
 
         internal static object Root
index 44b7dfb..7fb1d8b 100755 (executable)
@@ -71,7 +71,8 @@ namespace Tizen.NUI.EXaml
         {
             int typeIndex = int.Parse(childOp.ValueList[0] as string);
             string name = childOp.ValueList[1] as string;
-            globalDataList.Operations.Add(new GatherMethod(globalDataList, typeIndex, name));
+            var paramList = childOp.ValueList[2] as List<object>;
+            globalDataList.Operations.Add(new GatherMethod(globalDataList, typeIndex, name, paramList));
         }
     }
 }
index 00d4405..3e1b7d9 100755 (executable)
@@ -26,14 +26,16 @@ namespace Tizen.NUI.EXaml
 {
     internal class CreateInstance : Operation
     {
-        public CreateInstance(GlobalDataList globalDataList, int typeIndex, List<object> paramList = null)
+        public CreateInstance(GlobalDataList globalDataList, int typeIndex, int xFactoryMethodIndex, List<object> paramList = null)
         {
             this.typeIndex = typeIndex;
             this.paramList = paramList;
             this.globalDataList = globalDataList;
+            this.xFactoryMethodIndex = xFactoryMethodIndex;
         }
 
         private GlobalDataList globalDataList;
+        private int xFactoryMethodIndex;
 
         public void Do()
         {
@@ -45,20 +47,38 @@ namespace Tizen.NUI.EXaml
             {
                 var type = globalDataList.GatheredTypes[typeIndex];
 
+                var xFactoryMethod = (0 <= xFactoryMethodIndex) ? globalDataList.GatheredMethods[xFactoryMethodIndex] : null;
+
                 if (null == paramList)
                 {
-                    globalDataList.GatheredInstances.Add(Activator.CreateInstance(type));
+                    if (null == xFactoryMethod)
+                    {
+                        globalDataList.GatheredInstances.Add(Activator.CreateInstance(type));
+                    }
+                    else
+                    {
+                        globalDataList.GatheredInstances.Add(xFactoryMethod.Invoke(null, Array.Empty<object>()));
+                    }
                 }
                 else
                 {
                     for (int i = 0; i < paramList.Count; i++)
                     {
-                        if (paramList[i] is Instance)
+                        if (paramList[i] is Instance instance)
                         {
-                            paramList[i] = globalDataList.GatheredInstances[(paramList[i] as Instance).Index];
+                            paramList[i] = globalDataList.GatheredInstances[instance.Index];
                         }
+
+                    }
+
+                    if (null == xFactoryMethod)
+                    {
+                        globalDataList.GatheredInstances.Add(Activator.CreateInstance(type, paramList.ToArray()));
+                    }
+                    else
+                    {
+                        globalDataList.GatheredInstances.Add(xFactoryMethod.Invoke(null, paramList.ToArray()));
                     }
-                    globalDataList.GatheredInstances.Add(Activator.CreateInstance(type, paramList.ToArray()));
                 }
             }
 
index 452d44a..da4d4c4 100755 (executable)
@@ -27,23 +27,63 @@ namespace Tizen.NUI.EXaml
 {
     internal class GatherMethod : Operation
     {
-        public GatherMethod(GlobalDataList globalDataList, int typeIndex, string methodName)
+        public GatherMethod(GlobalDataList globalDataList, int typeIndex, string methodName, List<object> paramList)
         {
             this.typeIndex = typeIndex;
             this.methodName = methodName;
             this.globalDataList = globalDataList;
+            this.paramList = paramList;
         }
 
         private GlobalDataList globalDataList;
 
         public void Do()
         {
+            List<Type> paramTypeList = new List<Type>();
+
+            foreach (var obj in paramList)
+            {
+                int index = (int)obj;
+
+                if (null == paramTypeList)
+                {
+                    paramTypeList = new List<Type>();
+                }
+
+                if (index >= 0)
+                {
+                    paramTypeList.Add(globalDataList.GatheredTypes[index]);
+                }
+                else
+                {
+                    paramTypeList.Add(GetBaseType.GetBaseTypeByIndex(index));
+                }
+            }
+
+            Func<MethodInfo, bool> isMatch = m =>
+            {
+                if (m.Name != methodName)
+                    return false;
+                var p = m.GetParameters();
+                if (p.Length != paramTypeList.Count)
+                    return false;
+                for (var i = 0; i < p.Length; i++)
+                {
+                    if (p[i].ParameterType != paramTypeList[i])
+                    {
+                        return false;
+                    }
+                }
+                return true;
+            };
+
             var type = globalDataList.GatheredTypes[typeIndex];
-            var method = type.GetRuntimeMethods().FirstOrDefault(mi => mi.Name == methodName);
+            var method = type.GetRuntimeMethods().FirstOrDefault(isMatch);
             globalDataList.GatheredMethods.Add(method);
         }
 
         private int typeIndex;
         private string methodName;
+        private List<object> paramList;
     }
 }
diff --git a/src/Tizen.NUI/src/internal/EXaml/Utility/GetBaseType.cs b/src/Tizen.NUI/src/internal/EXaml/Utility/GetBaseType.cs
new file mode 100755 (executable)
index 0000000..067cf9a
--- /dev/null
@@ -0,0 +1,46 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Tizen.NUI.EXaml
+{
+    internal class GetBaseType
+    {
+        private static List<Type> baseTypes;
+        
+        internal static Type GetBaseTypeByIndex(int typeIndex)
+        {
+            if (null == baseTypes)
+            {
+                baseTypes = new List<Type>();
+
+                baseTypes.Add(typeof(sbyte));
+                baseTypes.Add(typeof(Int16));
+                baseTypes.Add(typeof(Int32));
+                baseTypes.Add(typeof(Int64));
+                baseTypes.Add(typeof(byte));
+                baseTypes.Add(typeof(UInt16));
+                baseTypes.Add(typeof(UInt32));
+                baseTypes.Add(typeof(UInt64));
+                baseTypes.Add(typeof(bool));
+                baseTypes.Add(typeof(string));
+                baseTypes.Add(typeof(object));
+                baseTypes.Add(typeof(char));
+                baseTypes.Add(typeof(decimal));
+                baseTypes.Add(typeof(float));
+                baseTypes.Add(typeof(double));
+                baseTypes.Add(typeof(TimeSpan));
+                baseTypes.Add(typeof(Uri));
+            }
+
+            var realIndex = typeIndex * -1 - 2;
+
+            if (realIndex >= baseTypes.Count)
+            {
+                throw new Exception($"Index {typeIndex} is not valid base type index");
+            }
+
+            return baseTypes[realIndex];
+        }
+    }
+}