From 3491fb025162f176d10216e2f960cbad42b3bba2 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jean-Philippe=20Bruy=C3=A8re?= Date: Fri, 20 Jan 2017 15:37:47 +0100 Subject: [PATCH] binding expression allowing named and unamed target, code clean and comments --- src/CompilerServices/CompilerServices.cs | 191 ++++++++++++----------- src/Instantiator.cs | 23 +-- 2 files changed, 109 insertions(+), 105 deletions(-) diff --git a/src/CompilerServices/CompilerServices.cs b/src/CompilerServices/CompilerServices.cs index 9ddf9991..86dbd66a 100644 --- a/src/CompilerServices/CompilerServices.cs +++ b/src/CompilerServices/CompilerServices.cs @@ -237,71 +237,6 @@ namespace Crow #endregion #region Reflexion helpers - /// - /// Gets all extension methods defined in assembly for Type - /// - /// Extension methods enumerable - /// Assembly - /// Extended type to search for - internal static IEnumerable GetExtensionMethods (Assembly assembly, - Type extendedType) - { - IEnumerable 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; - } - /// - /// search for extentions method in entry assembly then in crow assembly - /// - /// Extention MethodInfo - /// Extended type - /// Extention method name - 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 (); - } - /// - /// retrieve event handler in class or ancestors - /// - 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; } + /// + /// Gets all extension methods defined in assembly for Type + /// + /// Extension methods enumerable + /// Assembly + /// Extended type to search for + internal static IEnumerable GetExtensionMethods (Assembly assembly, + Type extendedType) + { + IEnumerable 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; + } + /// + /// search for extentions method in entry assembly then in crow assembly + /// + /// Extention MethodInfo + /// Extended type + /// Extention method name + 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 (); + } + /// + /// retrieve event handler in class or ancestors + /// + 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; + } + /// + /// search for an implicit conversion method in origine or destination classes + /// + 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 /// @@ -432,6 +448,7 @@ namespace Crow return; } } + /// /// Emit MSIL for conversion from orig type to dest type /// @@ -529,24 +546,7 @@ namespace Crow il.MarkLabel (endConvert); } - /// - /// search for an implicit conversion method in origine or destination classes - /// - 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; - } + /// /// Removes delegate from event handler by name /// @@ -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 (); } - /// - /// 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 /// - 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 diff --git a/src/Instantiator.cs b/src/Instantiator.cs index 305df437..883f3129 100644 --- a/src/Instantiator.cs +++ b/src/Instantiator.cs @@ -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; -- 2.47.3