From 66fb8b51703e2516a04504398d5ab7ed9af6840b Mon Sep 17 00:00:00 2001 From: jpbruyere Date: Sat, 24 Dec 2016 16:48:58 +0100 Subject: [PATCH] cancel for now reverse template binding and code clean and formating --- src/GraphicObjects/GraphicObject.cs | 4 + src/IML/MemberAddress.cs | 10 +- src/Instantiator.cs | 186 ++++++++++++++-------------- 3 files changed, 108 insertions(+), 92 deletions(-) diff --git a/src/GraphicObjects/GraphicObject.cs b/src/GraphicObjects/GraphicObject.cs index 6ca2466e..a2f9be7c 100644 --- a/src/GraphicObjects/GraphicObject.cs +++ b/src/GraphicObjects/GraphicObject.cs @@ -553,6 +553,10 @@ namespace Crow } protected virtual void onLogicalParentDataSourceChanged(object sender, DataSourceChangeEventArgs e){ ILayoutable tmp = Parent; + if (tmp == null) { + Debug.WriteLine ("parent is null for: " + this.ToString ()); + return; + } while (tmp != sender) { if (!(tmp as GraphicObject).localDataSourceIsNull) { OnDataSourceChanged (sender, e); diff --git a/src/IML/MemberAddress.cs b/src/IML/MemberAddress.cs index 7f3c93da..a131927e 100644 --- a/src/IML/MemberAddress.cs +++ b/src/IML/MemberAddress.cs @@ -29,11 +29,12 @@ namespace Crow.IML /// public struct MemberAddress { - string memberName; + public string memberName; public MemberInfo member; public NodeAddress Address; public PropertyInfo Property { get { return member as PropertyInfo; }} + public bool IsTemplateBinding { get { return Address == null ? false : Address.Count == 0; }} // public string Name { // get { return memberName; } // set { memberName = value; } @@ -45,6 +46,11 @@ namespace Crow.IML memberName = _member; member = null; + if (Address == null) + return; + if (Address.Count == 0) + return; + if (!findMember) return; if (!tryFindMember ()) @@ -85,6 +91,8 @@ namespace Crow.IML throw new Exception ("member already found"); if (Address == null) return false; + if (Address.Count == 0) + return false; Type t = Address.LastOrDefault ().CrowType; member = t.GetMember (memberName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance).FirstOrDefault (); diff --git a/src/Instantiator.cs b/src/Instantiator.cs index cdd229af..a0f8fe75 100644 --- a/src/Instantiator.cs +++ b/src/Instantiator.cs @@ -509,6 +509,93 @@ namespace Crow emitPropertyBindings (ctx, bindings.Key, bindings.Value); } } + void emitPropertyBindings(Context ctx, NodeAddress origine, Dictionary> bindings){ + Type origineNodeType = origine.NodeType; + + //value changed dyn method + DynamicMethod dm = new DynamicMethod ("dyn_valueChanged" + NewId, + typeof (void), CompilerServices.argsValueChange, true); + ILGenerator il = dm.GetILGenerator (256); + + System.Reflection.Emit.Label endMethod = il.DefineLabel (); + + il.DeclareLocal (typeof(object)); + + il.Emit (OpCodes.Nop); + + int i = 0; + foreach (KeyValuePair> bindingCase in bindings ) { + + System.Reflection.Emit.Label nextTest = il.DefineLabel (); + + #region member name test + //load source member name + il.Emit (OpCodes.Ldarg_1); + il.Emit (OpCodes.Ldfld, typeof(ValueChangeEventArgs).GetField ("MemberName")); + + il.Emit (OpCodes.Ldstr, bindingCase.Key);//load name to test + il.Emit (OpCodes.Ldc_I4_4);//StringComparison.Ordinal + il.Emit (OpCodes.Callvirt, CompilerServices.stringEquals); + il.Emit (OpCodes.Brfalse, nextTest);//if not equal, jump to next case + #endregion + + #region destination member affectations + PropertyInfo piOrig = origineNodeType.GetProperty (bindingCase.Key); + Type origineType = null; + if (piOrig != null) + origineType = piOrig.PropertyType; + foreach (MemberAddress ma in bindingCase.Value) { + if (ma.Address.Count == 0) + continue;//template binding + //first we have to load destination instance onto the stack, it is access + //with graphic tree functions deducted from nodes topology + il.Emit (OpCodes.Ldarg_0);//load source instance of ValueChanged event + + NodeAddress destination = ma.Address; + + CompilerServices.emitGetInstance (il, origine, destination); + + if (origineType != null){//prop less binding, no init requiered + //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); + il.Emit (OpCodes.Ldfld, typeof (ValueChangeEventArgs).GetField ("NewValue")); + + if (origineType == null)//property less binding, no init + CompilerServices.emitConvert (il, ma.Property.PropertyType); + else { + if (origineType.IsValueType) + ctx.il.Emit(OpCodes.Box, origineType); + CompilerServices.emitConvert (ctx.il, origineType, ma.Property.PropertyType); + CompilerServices.emitConvert (il, origineType, ma.Property.PropertyType); + + 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); + il.MarkLabel (nextTest); + + i++; + } + + il.MarkLabel (endMethod); + il.Emit (OpCodes.Ret); + + //store and emit Add in ctx + int dmIdx = cachedDelegates.Count; + cachedDelegates.Add (dm.CreateDelegate (typeof(EventHandler))); + ctx.emitCachedDelegateHandlerAddition (dmIdx, typeof(IValueChange).GetEvent ("ValueChanged"), origine); + } void emitTemplateBindings(Context ctx, Dictionary> bindings){ //value changed dyn method DynamicMethod dm = new DynamicMethod ("dyn_tmpValueChanged", @@ -576,6 +663,8 @@ namespace Crow #region destination member affectations foreach (MemberAddress ma in bindingCase.Value) { + if (ma.Address.Count == 0) + continue;//template binding //first we try to get memberInfo of new parent, if it doesn't exist, it's a propery less binding ilPC.Emit (OpCodes.Ldarg_2);//load new parent onto the stack for handler addition ilPC.Emit (OpCodes.Ldfld, CompilerServices.fiDSCNewDS); @@ -612,12 +701,12 @@ namespace Crow CompilerServices.emitConvert (il, ma.Property.PropertyType); -// //box ValueType -// ilPC.Emit (OpCodes.Ldloc_1);//push mi to check if it's a valuetype -// ilPC.Emit (OpCodes.Call, typeof(PropertyInfo).GetProperty("PropertyType").GetGetMethod()); -// ilPC.Emit (OpCodes.Call, typeof(Type).GetProperty("IsValueType").GetGetMethod()); -// System.Reflection.Emit.Label noBoxingRequired = ilPC.DefineLabel (); -// ilPC.Emit (OpCodes.Brfalse, noBoxingRequired); + // //box ValueType + // ilPC.Emit (OpCodes.Ldloc_1);//push mi to check if it's a valuetype + // ilPC.Emit (OpCodes.Call, typeof(PropertyInfo).GetProperty("PropertyType").GetGetMethod()); + // ilPC.Emit (OpCodes.Call, typeof(Type).GetProperty("IsValueType").GetGetMethod()); + // System.Reflection.Emit.Label noBoxingRequired = ilPC.DefineLabel (); + // ilPC.Emit (OpCodes.Brfalse, noBoxingRequired); CompilerServices.emitConvert (ilPC, ma.Property.PropertyType); @@ -662,91 +751,6 @@ namespace Crow ctx.emitCachedDelegateHandlerAddition(delDSIndex, typeof(GraphicObject).GetEvent("ParentChanged")); } - void emitPropertyBindings(Context ctx, NodeAddress origine, Dictionary> bindings){ - Type origineNodeType = origine.NodeType; - - //value changed dyn method - DynamicMethod dm = new DynamicMethod ("dyn_valueChanged" + NewId, - typeof (void), CompilerServices.argsValueChange, true); - ILGenerator il = dm.GetILGenerator (256); - - System.Reflection.Emit.Label endMethod = il.DefineLabel (); - - il.DeclareLocal (typeof(object)); - - il.Emit (OpCodes.Nop); - - int i = 0; - foreach (KeyValuePair> bindingCase in bindings ) { - - System.Reflection.Emit.Label nextTest = il.DefineLabel (); - - #region member name test - //load source member name - il.Emit (OpCodes.Ldarg_1); - il.Emit (OpCodes.Ldfld, typeof(ValueChangeEventArgs).GetField ("MemberName")); - - il.Emit (OpCodes.Ldstr, bindingCase.Key);//load name to test - il.Emit (OpCodes.Ldc_I4_4);//StringComparison.Ordinal - il.Emit (OpCodes.Callvirt, CompilerServices.stringEquals); - il.Emit (OpCodes.Brfalse, nextTest);//if not equal, jump to next case - #endregion - - #region destination member affectations - PropertyInfo piOrig = origineNodeType.GetProperty (bindingCase.Key); - Type origineType = null; - if (piOrig != null) - origineType = piOrig.PropertyType; - foreach (MemberAddress ma in bindingCase.Value) { - //first we have to load destination instance onto the stack, it is access - //with graphic tree functions deducted from nodes topology - il.Emit (OpCodes.Ldarg_0);//load source instance of ValueChanged event - - NodeAddress destination = ma.Address; - - CompilerServices.emitGetInstance (il, origine, destination); - - if (origineType != null){//prop less binding, no init requiered - //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); - il.Emit (OpCodes.Ldfld, typeof (ValueChangeEventArgs).GetField ("NewValue")); - - if (origineType == null)//property less binding, no init - CompilerServices.emitConvert (il, ma.Property.PropertyType); - else { - if (origineType.IsValueType) - ctx.il.Emit(OpCodes.Box, origineType); - CompilerServices.emitConvert (ctx.il, origineType, ma.Property.PropertyType); - CompilerServices.emitConvert (il, origineType, ma.Property.PropertyType); - - 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); - il.MarkLabel (nextTest); - - i++; - } - - il.MarkLabel (endMethod); - il.Emit (OpCodes.Ret); - - //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 /// -- 2.47.3