From 20d9e145a5ce8e60996145f7f030652eb9ce7165 Mon Sep 17 00:00:00 2001 From: jpbruyere Date: Thu, 22 Dec 2016 19:38:49 +0100 Subject: [PATCH] =?utf8?q?New=20property=20binding,=20init=20emitted=20in?= =?utf8?q?=20ctx.=20=09modifi=C3=A9=C2=A0:=20=20=20=20=20=20=20=20=20src/C?= =?utf8?q?ompilerServices/CompilerServices.cs=20=09modifi=C3=A9=C2=A0:=20?= =?utf8?q?=20=20=20=20=20=20=20=20src/IML/Context.cs=20=09modifi=C3=A9?= =?utf8?q?=C2=A0:=20=20=20=20=20=20=20=20=20src/Instantiator.cs?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- src/CompilerServices/CompilerServices.cs | 19 +++-- src/IML/Context.cs | 8 ++- src/Instantiator.cs | 92 +++++++----------------- 3 files changed, 43 insertions(+), 76 deletions(-) diff --git a/src/CompilerServices/CompilerServices.cs b/src/CompilerServices/CompilerServices.cs index de49d32d..7dcfd972 100644 --- a/src/CompilerServices/CompilerServices.cs +++ b/src/CompilerServices/CompilerServices.cs @@ -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); } diff --git a/src/IML/Context.cs b/src/IML/Context.cs index ec97c3d8..de5f480c 100644 --- a/src/IML/Context.cs +++ b/src/IML/Context.cs @@ -100,7 +100,7 @@ namespace Crow.IML Names[name] = new List(); 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){ + /// + /// Emits cached delegate handler addition in the context of instantiator (ctx) + /// + 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 diff --git a/src/Instantiator.cs b/src/Instantiator.cs index c90047dc..bea8c801 100644 --- a/src/Instantiator.cs +++ b/src/Instantiator.cs @@ -94,8 +94,6 @@ namespace Crow List dsValueChangedDynMeths = new List(); List cachedDelegates = new List(); List templateCachedDelegateIndices = new List();//store indices of template delegate to be handled by root parentChanged event - Dictionary bindingDelegates = new Dictionary();//valuechanged del - Dictionary bindingInitializer = new Dictionary();//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 - /// - /// 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. - /// - 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).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).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).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).GetMethod("Invoke")); - - ctx.il.MarkLabel (labContinue); - } - /// /// 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 /// void emitBindingDelegates(Context ctx){ foreach (KeyValuePair>> 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> bindings){ + void emitTemplateBindings(Context ctx, Dictionary> 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> bindings){ + void emitPropertyBindings(Context ctx, NodeAddress origine, Dictionary> 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)); - bindingInitializer [origine.ToString()] = dmInit.CreateDelegate (typeof(Action)); + //store and emit Add in ctx + int dmIdx = cachedDelegates.Count; + cachedDelegates.Add (dm.CreateDelegate (typeof(EventHandler))); + ctx.emitCachedDelegateHandlerAddition (dmIdx, typeof(IValueChange).GetEvent ("ValueChanged"), origine); } /// /// create the valuechanged handler, the datasourcechanged handler and emit event handling /// - 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; -- 2.47.3