]> O.S.I.I.S - jp/crow.git/commitdiff
New property binding, init emitted in ctx.
authorjpbruyere <jp.bruyere@hotmail.com>
Thu, 22 Dec 2016 18:38:49 +0000 (19:38 +0100)
committerjpbruyere <jp.bruyere@hotmail.com>
Thu, 22 Dec 2016 18:38:49 +0000 (19:38 +0100)
modifié :         src/CompilerServices/CompilerServices.cs
modifié :         src/IML/Context.cs
modifié :         src/Instantiator.cs

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

index de49d32de992b1fdeab6230eb4f4aa7f31cb891a..7dcfd9724c7c3430d9f4917ffa4122f5b4d48fdf 100644 (file)
@@ -667,15 +667,22 @@ namespace Crow
                        return null;
                }
                public static void emitGetInstance (ILGenerator il, NodeAddress orig, NodeAddress dest){
-                       if (orig.Count < dest.Count) {
-                               for (int i = orig.Count - 1; i < dest.Count - 1; i++)
-                                       emitGetChild (il, dest [i].CrowType, dest [i + 1].Index);
-                       } else {
-                               for (int j = dest.Count; j < orig.Count; j++)
-                                       il.Emit (OpCodes.Callvirt, typeof(ILayoutable).GetProperty ("Parent").GetGetMethod ());
+                       int ptr = 0;
+                       while (orig [ptr] == dest [ptr]) {
+                               ptr++;
+                               if (ptr == orig.Count || ptr == dest.Count)
+                                       break;
+                       }
+                       for (int i = 0; i < orig.Count - ptr; i++)
+                               il.Emit (OpCodes.Callvirt, typeof(ILayoutable).GetProperty ("Parent").GetGetMethod ());
+                       while (ptr < dest.Count) {
+                               emitGetChild (il, dest [ptr-1].CrowType, dest [ptr].Index);
+                               ptr++;
                        }
                }
                public static void emitGetInstance (ILGenerator il, NodeAddress dest){
+                       if (dest == null)
+                               return;
                        for (int i = 0; i < dest.Count - 1; i++)
                                emitGetChild (il, dest [i].CrowType, dest [i + 1].Index);
                }
index ec97c3d83e42c75b20be70aabc458e822fa9d085..de5f480cabdb7fc56ef18ea0d324fe4d2f0f28f8 100644 (file)
@@ -100,7 +100,7 @@ namespace Crow.IML
                                Names[name] = new List<NodeAddress>();
                        Names[name].Add(CurrentNodeAddress);
                }
-               public void ProcessBindingDefinition(){//TODO:methodinfo fetching is redundant with early parsing
+               public void ResolveNamedTargets(){//TODO:methodinfo fetching is redundant with early parsing
                        foreach (BindingDefinition bd in UnresolvedTargets) {
                                if (bd.HasUnresolvedTargetName) {
                                        try {
@@ -156,8 +156,12 @@ namespace Crow.IML
                        CompilerServices.emitSetCurInterface (il);
                }
 
-               public void emitCachedDelegateHandlerAddition(int index, EventInfo evt){
+               /// <summary>
+               /// Emits cached delegate handler addition in the context of instantiator (ctx)
+               /// </summary>
+               public void emitCachedDelegateHandlerAddition(int index, EventInfo evt, NodeAddress address = null){
                        il.Emit(OpCodes.Ldloc_0);//load ref to current graphic object
+                       CompilerServices.emitGetInstance (il, address);
                        il.Emit(OpCodes.Ldarg_0);//load ref to this instanciator onto the stack
                        il.Emit(OpCodes.Ldfld, typeof(Instantiator).GetField("cachedDelegates", BindingFlags.Instance | BindingFlags.NonPublic));
                        il.Emit(OpCodes.Ldc_I4, index);//load delegate index
index c90047dc1740521cd9164ef8409329463e09c296..bea8c80189794c8567e3026dd4b5bd11ad4e1a7f 100644 (file)
@@ -94,8 +94,6 @@ 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;
 
                #region IML parsing
@@ -112,7 +110,7 @@ namespace Crow
                        foreach (int idx in templateCachedDelegateIndices)
                                ctx.emitCachedDelegateHandlerAddition(idx, typeof(GraphicObject).GetEvent("ParentChanged"));
 
-                       ctx.ProcessBindingDefinition ();
+                       ctx.ResolveNamedTargets ();
 
                        emitBindingDelegates (ctx);
 
@@ -155,7 +153,7 @@ namespace Crow
 
                        emitGOLoad (ctx, tmpXml);
 
-                       emitCheckAndBindValueChanged (ctx);
+                       //emitCheckAndBindValueChanged (ctx);
                }
                void emitTemplateLoad (Context ctx, string tmpXml) {
                        //if its a template, first read template elements
@@ -384,7 +382,7 @@ namespace Crow
                        BindingDefinition bindingDef = splitBindingExp (sourceNA, sourceMember, expression);
 
                        if (bindingDef.IsDataSourceBinding)//bind on data source
-                               emitDataSourceBindingDelegate (ctx, sourceMember, bindingDef.TargetMember);
+                               emitDataSourceBindings (ctx, sourceMember, bindingDef.TargetMember);
                        else
                                ctx.StorePropertyBinding (bindingDef);
                }
@@ -460,42 +458,6 @@ 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 ();
-                       //first, test if current node is in bindingDelegate dictionnary
-                       ctx.il.Emit(OpCodes.Ldarg_0);//load ref to this instanciator onto the stack
-                       ctx.il.Emit(OpCodes.Ldfld, typeof(Instantiator).GetField("bindingDelegates", BindingFlags.Instance | BindingFlags.NonPublic));
-                       ctx.il.Emit (OpCodes.Ldstr, strNA);//load binding id for current node
-                       ctx.il.Emit (OpCodes.Call, typeof(Dictionary<string,Delegate>).GetMethod ("ContainsKey"));
-
-                       ctx.il.Emit (OpCodes.Brfalse, labContinue);//if not present, do nothing
-
-                       ctx.il.Emit (OpCodes.Ldloc_0);//load current instance for event add
-                       //fetch delegate
-                       ctx.il.Emit(OpCodes.Ldarg_0);//load ref to this instanciator onto the stack
-                       ctx.il.Emit(OpCodes.Ldfld, typeof(Instantiator).GetField("bindingDelegates", BindingFlags.Instance | BindingFlags.NonPublic));
-                       ctx.il.Emit (OpCodes.Ldstr, strNA);//load binding id for current node
-                       ctx.il.Emit (OpCodes.Callvirt, typeof(Dictionary<string, Delegate>).GetMethod ("get_Item", new Type[] { typeof(string) }));
-
-                       //attach to valuechanged handler
-                       ctx.il.Emit(OpCodes.Callvirt, typeof(IValueChange).GetEvent("ValueChanged").AddMethod);
-
-                       //call initializer
-                       ctx.il.Emit(OpCodes.Ldarg_0);//load ref to this instanciator onto the stack
-                       ctx.il.Emit(OpCodes.Ldfld, typeof(Instantiator).GetField("bindingInitializer", BindingFlags.Instance | BindingFlags.NonPublic));
-                       ctx.il.Emit (OpCodes.Ldstr, strNA);//load binding id for current node
-                       ctx.il.Emit (OpCodes.Call, typeof(Dictionary<string, Delegate>).GetMethod ("get_Item", new Type[] { typeof(string) }));
-                       ctx.il.Emit (OpCodes.Ldloc_0);//load current instance, passed as arg to invoke initializer
-                       ctx.il.Emit(OpCodes.Callvirt, typeof(Action<object>).GetMethod("Invoke"));
-
-                       ctx.il.MarkLabel (labContinue);
-               }
-
                /// <summary>
                /// Compile events expression in IML attributes, and store the result in the instanciator
                /// Those handlers will be bound when instatiing
@@ -696,13 +658,13 @@ namespace Crow
                /// </summary>
                void emitBindingDelegates(Context ctx){
                        foreach (KeyValuePair<NodeAddress,Dictionary<string, List<MemberAddress>>> bindings in ctx.Bindings ) {
-                               if (bindings.Key.Count == 0)
-                                       emitTemplateBindingDelegate (ctx, bindings.Value);
+                               if (bindings.Key.Count == 0)//template binding
+                                       emitTemplateBindings (ctx, bindings.Value);
                                else
-                                       emitBindingDelegate (bindings.Key, bindings.Value);
+                                       emitPropertyBindings (ctx,  bindings.Key, bindings.Value);
                        }
                }
-               void emitTemplateBindingDelegate(Context ctx, Dictionary<string, List<MemberAddress>> bindings){
+               void emitTemplateBindings(Context ctx, Dictionary<string, List<MemberAddress>> bindings){
                        //value changed dyn method
                        DynamicMethod dm = new DynamicMethod ("dyn_tmpValueChanged",
                                typeof (void), CompilerServices.argsValueChange, true);
@@ -826,15 +788,9 @@ namespace Crow
 
                        ctx.emitCachedDelegateHandlerAddition(delDSIndex, typeof(GraphicObject).GetEvent("ParentChanged"));
                }
-               void emitBindingDelegate(NodeAddress origine, Dictionary<string, List<MemberAddress>> bindings){
+               void emitPropertyBindings(Context ctx, NodeAddress origine, Dictionary<string, List<MemberAddress>> bindings){
                        Type origineNodeType = origine.NodeType;
 
-                       //init method, current instance passed as arg
-                       DynamicMethod dmInit = new DynamicMethod ("dyn_initBinding_" + NewId.ToString(),
-                               typeof (void), new Type[] {typeof(object)}, true);
-                       ILGenerator ilInit = dmInit.GetILGenerator (256);
-                       ilInit.Emit (OpCodes.Nop);
-
                        //value changed dyn method
                        DynamicMethod dm = new DynamicMethod ("dyn_valueChanged",
                                typeof (void), CompilerServices.argsValueChange, true);
@@ -844,7 +800,6 @@ namespace Crow
                        System.Reflection.Emit.Label endMethod = il.DefineLabel ();
 
                        il.DeclareLocal (typeof(object));
-                       ilInit.DeclareLocal (typeof(object));
 
                        il.Emit (OpCodes.Nop);
 
@@ -879,13 +834,14 @@ namespace Crow
                                        CompilerServices.emitGetInstance (il, origine, destination);
 
                                        if (origineType != null){//prop less binding, no init requiered
-                                               //for initialisation dynmeth, load current instance
-                                               ilInit.Emit(OpCodes.Ldarg_0);
-                                               CompilerServices.emitGetInstance (ilInit, origine, destination);
-
-                                               //init dynmeth: load actual value
-                                               ilInit.Emit (OpCodes.Ldarg_0);
-                                               ilInit.Emit (OpCodes.Callvirt, origineNodeType.GetProperty (bindingCase.Key).GetGetMethod());
+                                               //for initialisation dynmeth, push destination instance loc_0 is root node in ctx
+                                               ctx.il.Emit(OpCodes.Ldloc_0);
+                                               CompilerServices.emitGetInstance (ctx.il, destination);
+
+                                               //init dynmeth: load actual value from origine
+                                               ctx.il.Emit (OpCodes.Ldloc_0);
+                                               CompilerServices.emitGetInstance (ctx.il, origine);
+                                               ctx.il.Emit (OpCodes.Callvirt, origineNodeType.GetProperty (bindingCase.Key).GetGetMethod());
                                        }
                                        //load new value
                                        il.Emit (OpCodes.Ldarg_1);
@@ -895,14 +851,13 @@ namespace Crow
                                                CompilerServices.emitConvert (il, ma.Property.PropertyType);
                                        else {
                                                if (origineType.IsValueType)
-                                                       ilInit.Emit(OpCodes.Box, origineType);
-                                               CompilerServices.emitConvert (ilInit, origineType, ma.Property.PropertyType);
+                                                       ctx.il.Emit(OpCodes.Box, origineType);
+                                               CompilerServices.emitConvert (ctx.il, origineType, ma.Property.PropertyType);
                                                CompilerServices.emitConvert (il, origineType, ma.Property.PropertyType);
 
-                                               ilInit.Emit (OpCodes.Callvirt, ma.Property.GetSetMethod());//set init value
+                                               ctx.il.Emit (OpCodes.Callvirt, ma.Property.GetSetMethod());//set init value
                                        }
                                        il.Emit (OpCodes.Callvirt, ma.Property.GetSetMethod());//set value on value changes
-
                                }
                                #endregion
                                il.Emit (OpCodes.Br, endMethod);
@@ -911,17 +866,18 @@ namespace Crow
                                i++;
                        }
 
-                       ilInit.Emit (OpCodes.Ret);
                        il.MarkLabel (endMethod);
                        il.Emit (OpCodes.Ret);
 
-                       bindingDelegates [origine.ToString()] = dm.CreateDelegate (typeof(EventHandler<ValueChangeEventArgs>));
-                       bindingInitializer [origine.ToString()] = dmInit.CreateDelegate (typeof(Action<object>));
+                       //store and emit Add in ctx
+                       int dmIdx = cachedDelegates.Count;
+                       cachedDelegates.Add (dm.CreateDelegate (typeof(EventHandler<ValueChangeEventArgs>)));
+                       ctx.emitCachedDelegateHandlerAddition (dmIdx, typeof(IValueChange).GetEvent ("ValueChanged"), origine);
                }
                /// <summary>
                /// create the valuechanged handler, the datasourcechanged handler and emit event handling
                /// </summary>
-               void emitDataSourceBindingDelegate(Context ctx, string sourceMember, string dataSourceMember){
+               void emitDataSourceBindings(Context ctx, string sourceMember, string dataSourceMember){
                        DynamicMethod dm = null;
                        ILGenerator il = null;
                        int dmVC = 0;