diff options
| author | jpbruyere <jp.bruyere@hotmail.com> | 2016-12-22 19:38:49 +0100 |
|---|---|---|
| committer | jpbruyere <jp.bruyere@hotmail.com> | 2016-12-22 19:38:49 +0100 |
| commit | 20d9e145a5ce8e60996145f7f030652eb9ce7165 (patch) | |
| tree | 43b5b7947390e2b0a08122d10e50f80c088399c2 /src | |
| parent | 15092ce68614c7bc0acf968daf3c936f6504c42f (diff) | |
New property binding, init emitted in ctx.
modifié : src/CompilerServices/CompilerServices.cs
modifié : src/IML/Context.cs
modifié : src/Instantiator.cs
Diffstat (limited to 'src')
| -rw-r--r-- | src/CompilerServices/CompilerServices.cs | 19 | ||||
| -rw-r--r-- | src/IML/Context.cs | 8 | ||||
| -rw-r--r-- | src/Instantiator.cs | 90 |
3 files changed, 42 insertions, 75 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<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 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<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); } @@ -461,42 +459,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 /// </summary> @@ -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); + //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 - ilInit.Emit (OpCodes.Ldarg_0); - ilInit.Emit (OpCodes.Callvirt, origineNodeType.GetProperty (bindingCase.Key).GetGetMethod()); + //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; |