]> O.S.I.I.S - jp/crow.git/commitdiff
Template handler binding, name resolution, IsTemplateBinding property in
authorjpbruyere <jp.bruyere@hotmail.com>
Thu, 22 Dec 2016 09:08:15 +0000 (10:08 +0100)
committerjpbruyere <jp.bruyere@hotmail.com>
Thu, 22 Dec 2016 09:08:15 +0000 (10:08 +0100)
BindingDefinition class
modifié :         src/CompilerServices/CompilerServices.cs
modifié :         src/IML/BindingDefinition.cs
modifié :         src/IML/Context.cs
modifié :         src/Instantiator.cs

src/CompilerServices/CompilerServices.cs
src/IML/BindingDefinition.cs
src/IML/Context.cs
src/Instantiator.cs

index ba824c621f0f875e70bb48d07340d0848217f22c..16ad5d8e95a70781f4d204dbcf7dcc2edb519cc5 100644 (file)
@@ -48,7 +48,7 @@ namespace Crow
 
                internal static EventInfo eiDSChange = typeof (GraphicObject).GetEvent ("DataSourceChanged");
                internal static MethodInfo miInvokeDSChange = eiDSChange.EventHandlerType.GetMethod ("Invoke");
-               internal static Type [] argsDSChange = {typeof (object), typeof (object), miInvokeDSChange.GetParameters () [1].ParameterType };
+               internal static Type [] argsBoundDSChange = {typeof (object), typeof (object), miInvokeDSChange.GetParameters () [1].ParameterType };
                internal static FieldInfo fiDSCNewDS = typeof (DataSourceChangeEventArgs).GetField ("NewDataSource");
 
                internal static MethodInfo miCreateBoundDelegate = typeof(DynamicMethod).
index 19a54d0960bee43d7f57fda429861a554933bc54..2c3fecdcc5717920e5c47ab4360d70174be6708b 100644 (file)
@@ -51,6 +51,7 @@ namespace Crow.IML
                #endregion
 
                public bool IsDataSourceBinding { get { return TargetNA == null; }}
+               public bool IsTemplateBinding { get { return IsDataSourceBinding ? false : TargetNA.Count == 0; }}
                public bool HasUnresolvedTargetName { get { return !string.IsNullOrEmpty(TargetName); }}
 
                /// <summary>
index 104633c6d53330999a8f7e8db7ae8683782a72cd..393bab2115f4ab0622eaeaf506c6d6dec6d56adb 100644 (file)
@@ -99,8 +99,10 @@ namespace Crow.IML
                }
                public void ResolveNames (){
                        foreach (BindingDefinition bd in UnresolvedTargets) {
-                               if (!Names.ContainsKey (bd.TargetName))
-                                       throw new Exception ("Target Name '" + bd.TargetName + "' not found");
+                               if (!Names.ContainsKey (bd.TargetName)) {
+                                       System.Diagnostics.Debug.WriteLine ("Target Name '" + bd.TargetName + "' not found");
+                                       continue;
+                               }
                                NodeAddress resolvedNA = null;
                                foreach (NodeAddress na in Names[bd.TargetName]) {
                                        bool naMatch = true;
@@ -116,10 +118,11 @@ namespace Crow.IML
                                        }
                                }
                                if (resolvedNA == null)
-                                       throw new Exception ("Target Name '" + bd.TargetName + "' not found");
-
-                               bd.ResolveTargetName (resolvedNA);
-                               StorePropertyBinding (bd);
+                                       System.Diagnostics.Debug.WriteLine ("Target Name '" + bd.TargetName + "' not found");
+                               else {
+                                       bd.ResolveTargetName (resolvedNA);
+                                       StorePropertyBinding (bd);
+                               }
                        }
                }
 
index 0ff9e4dec266f831fd14184a0842356fb123670a..90cb80451d7578c9fdf572d643401a10a47ceae3 100644 (file)
@@ -93,6 +93,7 @@ namespace Crow
 
                List<DynamicMethod> dsValueChangedDynMeths = new List<DynamicMethod>();
                List<Delegate> cachedDelegates = new List<Delegate>();
+               List<int> templateCachedDelegateIndices = new List<int>();//store indices of template delegate to be handled by root parentChanged event
                Dictionary<string, Delegate> bindingDelegates = new Dictionary<string, Delegate>();//valuechanged del
                Dictionary<string, Delegate> bindingInitializer = new Dictionary<string, Delegate>();//initialize with actual values of binding origine
                Delegate templateBinding;
@@ -108,6 +109,10 @@ namespace Crow
                        emitLoader (reader, ctx);
                        ctx.nodesStack.Pop ();
 
+                       foreach (int idx in templateCachedDelegateIndices)
+                               ctx.emitCachedDelegateHandlerAddition(idx, typeof(GraphicObject).GetEvent("ParentChanged"));
+
+                       ctx.ResolveNames ();
 
                        emitBindingDelegates (ctx);
 
@@ -455,6 +460,10 @@ namespace Crow
                }
                #endregion
 
+               /// <summary>
+               /// Emits in the instantiator ctx the search for normal (in the current graphic tree) property binding delegates for actual element,
+               /// and add event if found.
+               /// </summary>
                void emitCheckAndBindValueChanged(Context ctx){
                        System.Reflection.Emit.Label labContinue = ctx.il.DefineLabel ();
                        string strNA = ctx.CurrentNodeAddress.ToString ();
@@ -497,7 +506,6 @@ namespace Crow
                        Debug.WriteLine ("\tCompile Event Source ");
                        #endif
 
-
                        #region Retrieve EventHandler parameter type
                        MethodInfo evtInvoke = sourceEvent.EventHandlerType.GetMethod ("Invoke");
                        ParameterInfo [] evtParams = evtInvoke.GetParameters ();
@@ -509,10 +517,8 @@ namespace Crow
                                                   typeof(void),
                                                   args, true);
 
-
                        #region IL generation
                        NodeAddress currentNode = ctx.CurrentNodeAddress;
-                       string strNA = currentNode.ToString();
 
                        ILGenerator il = dm.GetILGenerator (256);
                        il.Emit (OpCodes.Nop);
@@ -623,6 +629,9 @@ namespace Crow
                        NodeAddress currentNode = ctx.CurrentNodeAddress;
                        BindingDefinition bindingDef = splitBindingExp (currentNode, sourceEvent.Name, expression);
 
+                       if (bindingDef.HasUnresolvedTargetName)
+                               return;
+
                        string bindOnEventName = null;
 
                        if (bindingDef.TargetNA == null)//datasource handler
@@ -634,9 +643,10 @@ namespace Crow
                                //we need to bind datasource method to source event
                                DynamicMethod dm = new DynamicMethod ("dyn_dschangedForHandler",
                                        typeof (void),
-                                       CompilerServices.argsDSChange, true);
+                                       CompilerServices.argsBoundDSChange, true);
 
                                ILGenerator il = dm.GetILGenerator (256);
+                               System.Reflection.Emit.Label cancel = il.DefineLabel ();
 
                                il.DeclareLocal (typeof(MethodInfo));//used to cancel binding if method doesn't exist
 
@@ -645,14 +655,19 @@ namespace Crow
                                //fetch method in datasource and test if it exist
                                il.Emit (OpCodes.Ldarg_2);//load new datasource
                                il.Emit (OpCodes.Ldfld, CompilerServices.fiDSCNewDS);
+                               il.Emit (OpCodes.Brfalse, cancel);//cancel if new datasource is null
+                               il.Emit (OpCodes.Ldarg_2);//load new datasource
+                               il.Emit (OpCodes.Ldfld, CompilerServices.fiDSCNewDS);
                                il.Emit (OpCodes.Ldstr, bindingDef.TargetMember);//load handler method name
                                il.Emit (OpCodes.Call, typeof(CompilerServices).GetMethod("getMethodInfoWithReflexion", BindingFlags.Static | BindingFlags.Public));
                                il.Emit (OpCodes.Stloc_0);//save MethodInfo
                                il.Emit (OpCodes.Ldloc_0);//push mi for test if null
-                               System.Reflection.Emit.Label methodNotFound = il.DefineLabel ();
-                               il.Emit (OpCodes.Brfalse, methodNotFound);
+
+                               il.Emit (OpCodes.Brfalse, cancel);
 
                                il.Emit (OpCodes.Ldarg_1);//load datasource change source where the event handler is as 1st arg of handler.add
+                               if (bindingDef.IsTemplateBinding)//fetch source instance with address
+                                       emitGetInstance (il, bindingDef.SourceNA);
 
                                //loat handlerType of sourceEvent to create delegate (1st arg)
                                il.Emit(OpCodes.Ldtoken, sourceEvent.EventHandlerType);
@@ -665,14 +680,21 @@ namespace Crow
                                        new Type[] {typeof(Type), typeof(object), typeof(MethodInfo)}));//create bound delegate
                                il.Emit(OpCodes.Callvirt, sourceEvent.AddMethod);//call add event
 
-                               il.MarkLabel(methodNotFound);
+                               System.Reflection.Emit.Label finish = il.DefineLabel ();
+                               il.Emit (OpCodes.Br, finish);
+                               il.MarkLabel (cancel);
+                               il.EmitWriteLine (sourcePath + ": Handler method not found: " + bindingDef.TargetMember);
+                               il.MarkLabel (finish);
                                il.Emit (OpCodes.Ret);
 
                                //store dschange delegate in instatiator instance for access while instancing graphic object
                                int delDSIndex = cachedDelegates.Count;
                                cachedDelegates.Add(dm.CreateDelegate (CompilerServices.ehTypeDSChange, this));
 
-                               ctx.emitCachedDelegateHandlerAddition(delDSIndex, typeof(GraphicObject).GetEvent(bindOnEventName));
+                               if (bindingDef.TargetNA == null)
+                                       ctx.emitCachedDelegateHandlerAddition(delDSIndex, typeof(GraphicObject).GetEvent("DataSourceChanged"));
+                               else //template handler binding
+                                       templateCachedDelegateIndices.Add(delDSIndex);
                        }
                }
                /// <summary>
@@ -697,7 +719,7 @@ namespace Crow
                        //create parentchanged dyn meth in parallel to have only one loop over bindings
                        DynamicMethod dmPC = new DynamicMethod ("dyn_InitAndParentChanged",
                                typeof (void),
-                               CompilerServices.argsDSChange, true);
+                               CompilerServices.argsBoundDSChange, true);
                        ILGenerator ilPC = dmPC.GetILGenerator (256);
 
                        il.Emit (OpCodes.Nop);
@@ -970,7 +992,7 @@ namespace Crow
                        //dm is bound to the instanciator instance to have access to cached dyn meth and delegates
                        dm = new DynamicMethod ("dyn_dschanged",
                                typeof (void),
-                               CompilerServices.argsDSChange, true);
+                               CompilerServices.argsBoundDSChange, true);
 
                        il = dm.GetILGenerator (256);
 
@@ -1073,9 +1095,9 @@ namespace Crow
                        if (destType == typeof(string))
                                il.Emit (OpCodes.Callvirt, CompilerServices.miObjToString);
                        else if (origType.IsValueType) {
-                               if (destType != origType)
+                               if (destType != origType) {
                                        il.Emit (OpCodes.Callvirt, CompilerServices.GetConvertMethod (destType));
-                               else
+                               }else
                                        il.Emit (OpCodes.Unbox_Any, destType);//TODO:double check this
                        } else {
                                if (origType.IsAssignableFrom(destType))