]> O.S.I.I.S - jp/crow.git/commitdiff
binding expression allowing named and unamed target, code clean and
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Fri, 20 Jan 2017 14:37:47 +0000 (15:37 +0100)
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Fri, 20 Jan 2017 15:11:04 +0000 (16:11 +0100)
comments

src/CompilerServices/CompilerServices.cs
src/Instantiator.cs

index 9ddf999187d1fa07062b958246a0a80603cf6bf9..86dbd66a26ffa5243534aab812bd5d7d7f39b957 100644 (file)
@@ -237,71 +237,6 @@ namespace Crow
                #endregion
 
                #region Reflexion helpers
-               /// <summary>
-               /// Gets all extension methods defined in assembly for Type
-               /// </summary>
-               /// <returns>Extension methods enumerable</returns>
-               /// <param name="assembly">Assembly</param>
-               /// <param name="extendedType">Extended type to search for</param>
-               internal static IEnumerable<MethodInfo> GetExtensionMethods (Assembly assembly,
-                       Type extendedType)
-               {
-                       IEnumerable<MethodInfo> query = null;
-                       Type curType = extendedType;
-
-                       do {
-                               query = from type in assembly.GetTypes ()
-                                               where type.IsSealed && !type.IsGenericType && !type.IsNested
-                                       from method in type.GetMethods (BindingFlags.Static
-                                               | BindingFlags.Public | BindingFlags.NonPublic)
-                                               where method.IsDefined (typeof (ExtensionAttribute), false)
-                                               where method.GetParameters () [0].ParameterType == curType
-                                       select method;
-
-                               if (query.Count () > 0)
-                                       break;
-
-                               curType = curType.BaseType;
-                       } while (curType != null);
-
-                       return query;
-               }
-               /// <summary>
-               /// search for extentions method in entry assembly then in crow assembly
-               /// </summary>
-               /// <returns>Extention MethodInfo</returns>
-               /// <param name="t">Extended type</param>
-               /// <param name="methodName">Extention method name</param>
-               internal static MethodInfo SearchExtMethod(Type t, string methodName){
-                       MethodInfo mi = null;
-                       mi = GetExtensionMethods (Assembly.GetEntryAssembly(), t)
-                               .Where (em => em.Name == methodName).FirstOrDefault ();
-                       if (mi != null)
-                               return mi;
-
-                       return GetExtensionMethods (Assembly.GetExecutingAssembly(), t)
-                               .Where (em => em.Name == methodName).FirstOrDefault ();
-               }
-               /// <summary>
-               /// retrieve event handler in class or ancestors
-               /// </summary>
-               static FieldInfo getEventHandlerField (Type type, string eventName)
-               {
-                       FieldInfo fi;
-                       Type ty = type;
-                       do {
-                               fi = ty.GetField (eventName,
-                                       BindingFlags.NonPublic |
-                                       BindingFlags.Instance |
-                                       BindingFlags.GetField);
-                               ty = ty.BaseType;
-                               if (ty == null)
-                                       break;
-                       } while (fi == null);
-                       return fi;
-               }
-
-
                static MemberInfo getMemberInfoWithReflexion(object instance, string member){
                        return instance.GetType ().GetMember (member)?.FirstOrDefault();
                }
@@ -374,6 +309,87 @@ namespace Crow
 
                        return null;
                }
+               /// <summary>
+               /// Gets all extension methods defined in assembly for Type
+               /// </summary>
+               /// <returns>Extension methods enumerable</returns>
+               /// <param name="assembly">Assembly</param>
+               /// <param name="extendedType">Extended type to search for</param>
+               internal static IEnumerable<MethodInfo> GetExtensionMethods (Assembly assembly,
+                       Type extendedType)
+               {
+                       IEnumerable<MethodInfo> query = null;
+                       Type curType = extendedType;
+
+                       do {
+                               query = from type in assembly.GetTypes ()
+                                               where type.IsSealed && !type.IsGenericType && !type.IsNested
+                                       from method in type.GetMethods (BindingFlags.Static
+                                               | BindingFlags.Public | BindingFlags.NonPublic)
+                                               where method.IsDefined (typeof (ExtensionAttribute), false)
+                                               where method.GetParameters () [0].ParameterType == curType
+                                       select method;
+
+                               if (query.Count () > 0)
+                                       break;
+
+                               curType = curType.BaseType;
+                       } while (curType != null);
+
+                       return query;
+               }
+               /// <summary>
+               /// search for extentions method in entry assembly then in crow assembly
+               /// </summary>
+               /// <returns>Extention MethodInfo</returns>
+               /// <param name="t">Extended type</param>
+               /// <param name="methodName">Extention method name</param>
+               internal static MethodInfo SearchExtMethod(Type t, string methodName){
+                       MethodInfo mi = null;
+                       mi = GetExtensionMethods (Assembly.GetEntryAssembly(), t)
+                               .Where (em => em.Name == methodName).FirstOrDefault ();
+                       if (mi != null)
+                               return mi;
+
+                       return GetExtensionMethods (Assembly.GetExecutingAssembly(), t)
+                               .Where (em => em.Name == methodName).FirstOrDefault ();
+               }
+               /// <summary>
+               /// retrieve event handler in class or ancestors
+               /// </summary>
+               static FieldInfo getEventHandlerField (Type type, string eventName)
+               {
+                       FieldInfo fi;
+                       Type ty = type;
+                       do {
+                               fi = ty.GetField (eventName,
+                                       BindingFlags.NonPublic |
+                                       BindingFlags.Instance |
+                                       BindingFlags.GetField);
+                               ty = ty.BaseType;
+                               if (ty == null)
+                                       break;
+                       } while (fi == null);
+                       return fi;
+               }
+               /// <summary>
+               /// search for an implicit conversion method in origine or destination classes
+               /// </summary>
+               static MethodInfo getImplicitOp(Type origType, Type dstType){
+                       foreach(MethodInfo mi in origType.GetMethods(BindingFlags.Public|BindingFlags.Static)){
+                               if (mi.Name == "op_Implicit") {
+                                       if (mi.ReturnType == dstType && mi.GetParameters ().FirstOrDefault ().ParameterType == origType)
+                                               return mi;
+                               }
+                       }
+                       foreach(MethodInfo mi in dstType.GetMethods(BindingFlags.Public|BindingFlags.Static)){
+                               if (mi.Name == "op_Implicit") {
+                                       if (mi.ReturnType == dstType && mi.GetParameters ().FirstOrDefault ().ParameterType == origType)
+                                               return mi;
+                               }
+                       }
+                       return null;
+               }
                #endregion
 
                /// <summary>
@@ -432,6 +448,7 @@ namespace Crow
                                return;
                        }
                }
+
                /// <summary>
                /// Emit MSIL for conversion from orig type to dest type
                /// </summary>
@@ -529,24 +546,7 @@ namespace Crow
 
                        il.MarkLabel (endConvert);
                }
-               /// <summary>
-               /// search for an implicit conversion method in origine or destination classes
-               /// </summary>
-               static MethodInfo getImplicitOp(Type origType, Type dstType){
-                       foreach(MethodInfo mi in origType.GetMethods(BindingFlags.Public|BindingFlags.Static)){
-                               if (mi.Name == "op_Implicit") {
-                                       if (mi.ReturnType == dstType && mi.GetParameters ().FirstOrDefault ().ParameterType == origType)
-                                               return mi;
-                               }
-                       }
-                       foreach(MethodInfo mi in dstType.GetMethods(BindingFlags.Public|BindingFlags.Static)){
-                               if (mi.Name == "op_Implicit") {
-                                       if (mi.ReturnType == dstType && mi.GetParameters ().FirstOrDefault ().ParameterType == origType)
-                                               return mi;
-                               }
-                       }
-                       return null;
-               }
+
                /// <summary>
                /// Removes delegate from event handler by name
                /// </summary>
@@ -601,6 +601,7 @@ namespace Crow
                        }
                        return Delegate.CreateDelegate (eventType, instance, mi);
                }
+
                public static Delegate compileDynEventHandler2(EventInfo sourceEvent, string expression, NodeAddress currentNode = null){
                        #if DEBUG_BINDING
                        Debug.WriteLine ("\tCompile Event {0}: {1}", sourceEvent.Name, expression);
@@ -647,7 +648,7 @@ namespace Crow
                                il.Emit (OpCodes.Ldarg_0);  //load sender ref onto the stack, the current node
 
                                if (lopParts.Length > 1) {
-                                       NodeAddress lopNA = getNodeAdressFromBindingExp (currentNode, lopParts);
+                                       NodeAddress lopNA = getNodeAdressFromBindingExp (currentNode, ref operandes [0]);
                                        CompilerServices.emitGetInstance (il, currentNode, lopNA);
                                        lopType = lopNA.NodeType;
                                }
@@ -771,7 +772,7 @@ namespace Crow
                                il.Emit (OpCodes.Ldarg_0);  //load sender ref onto the stack
 
                                if (lopParts.Length > 1) {
-                                       NodeAddress lopNA = getNodeAdressFromBindingExp (currentNode, lopParts);
+                                       NodeAddress lopNA = getNodeAdressFromBindingExp (currentNode, ref operandes [0]);
                                        CompilerServices.emitGetInstance (il, currentNode, lopNA);
                                        lopType = lopNA.NodeType;
                                }
@@ -876,29 +877,31 @@ namespace Crow
                        return exps.ToArray ();
                }
 
-
                /// <summary>
-               /// Gets the node adress from binding expression splitted with '/' starting at a given node
+               /// Gets the node adress from binding expression starting at sourceAddr
+               /// and return in expression remaining part
                /// </summary>
-               internal static NodeAddress getNodeAdressFromBindingExp(NodeAddress sourceAddr, string[] bindingExp){
+               internal static NodeAddress getNodeAdressFromBindingExp(NodeAddress sourceAddr, ref string expression){
                        int ptr = sourceAddr.Count - 1;
+                       string[] splitedExp = expression.Split ('/');
+
+                       if (splitedExp.Length < 2)//dataSource binding
+                               return null;
 
-                       //if exp start with '/' => Graphic tree parsing start at source
-                       if (string.IsNullOrEmpty (bindingExp [0])) {
-                               //TODO:
-                       } else if (bindingExp [0] == ".") { //search template root
+                       if (string.IsNullOrEmpty (splitedExp [0]) || splitedExp [0] == ".") {//search template root
                                ptr--;
                                while (ptr >= 0) {
                                        if (typeof(TemplatedControl).IsAssignableFrom (sourceAddr [ptr].CrowType))
                                                break;
                                        ptr--;
                                }
-                       } else if (bindingExp [0] == "..") { //search starting at current node
-                               int levelUp = bindingExp.Length - 1;
+                       } else if (splitedExp [0] == "..") { //search starting at current node
+                               int levelUp = splitedExp.Length - 1;
                                if (levelUp > ptr + 1)
                                        throw new Exception ("Binding error: try to bind outside IML source");
                                ptr -= levelUp;
                        }
+                       expression = splitedExp [splitedExp.Length - 1];
                        //TODO:change Template special address identified with Nodecount = 0 to something not using array count to 0,
                        //here linq is working without limits checking in compile option
                        //but defining a 0 capacity array with limits cheking enabled, cause 'out of memory' error
index 305df43726249d9b8502f42766aa02d5a80c3b5f..883f31291b13ee152badd6732c93632c9e528206 100644 (file)
@@ -87,7 +87,7 @@ namespace Crow
                }
                #endregion
 
-               public GraphicObject CreateInstance(Interface iface){                   
+               public GraphicObject CreateInstance(Interface iface){
                        return loader (iface) as GraphicObject;
                }
 
@@ -380,21 +380,22 @@ namespace Crow
                                        bindingDef.TwoWay = true;
                                        expression = expression.Substring (1);
                                }
-                               string[] bindingExp = expression.Split ('/');
 
-                               if (bindingExp.Length > 1)
-                                       bindingDef.TargetNA = CompilerServices.getNodeAdressFromBindingExp (sourceNA, bindingExp);
+                               string exp = expression;
+                               bindingDef.TargetNA = CompilerServices.getNodeAdressFromBindingExp (sourceNA, ref exp);
 
-                               string [] bindTrg = bindingExp.Last().Split ('.');
+                               string [] bindTrg = exp.Split ('.');
 
+                               if (bindTrg.Length == 0)
+                                       throw new Exception ("invalid binding expression: " + expression);
                                if (bindTrg.Length == 1)
                                        bindingDef.TargetMember = bindTrg [0];
-                               else if (bindTrg.Length == 2) {
-                                       //named target
-                                       bindingDef.TargetName = bindTrg[0];
-                                       bindingDef.TargetMember = bindTrg [1];
-                               } else
-                                       throw new Exception ("Syntax error in binding, expected 'go dot member'");
+                               else {
+                                       if (!string.IsNullOrEmpty(bindTrg[0]))//searchByName
+                                               bindingDef.TargetName = bindTrg[0];
+
+                                       bindingDef.TargetMember = exp.Substring (bindTrg[0].Length + 1);
+                               }
                        }
 
                        return bindingDef;