]> O.S.I.I.S - jp/crow.git/commitdiff
graphic tree bindings valuechanges implementation
authorjpbruyere <jp.bruyere@hotmail.com>
Tue, 22 Nov 2016 10:01:58 +0000 (11:01 +0100)
committerjpbruyere <jp.bruyere@hotmail.com>
Tue, 22 Nov 2016 10:01:58 +0000 (11:01 +0100)
src/CompilerServices/CompilerServices.cs
src/GraphicObjects/GraphicObject.cs
src/IML/Context.cs
src/IML/MemberAddress.cs
src/IML/Node.cs
src/IML/NodeAddress.cs
src/Instantiator.cs

index 18bc78ea663fb949dd88008bb267868400cdfc4c..85e240e9f270ef745fdeb1274fdfe65f29df9073 100644 (file)
@@ -12,7 +12,6 @@ namespace Crow
 {
        public static class CompilerServices
        {
-               static MethodInfo miAddBinding = typeof(GraphicObject).GetMethod ("BindMember");
                static FieldInfo miSetCurIface = typeof(GraphicObject).GetField ("currentInterface",
                        BindingFlags.NonPublic | BindingFlags.Instance);
                internal static MethodInfo stringEquals = typeof (string).GetMethod
@@ -40,7 +39,8 @@ namespace Crow
                #region ValueChange Reflexion member info
                internal static EventInfo eiValueChange = typeof (IValueChange).GetEvent ("ValueChanged");
                internal static MethodInfo miInvokeValueChange = eiValueChange.EventHandlerType.GetMethod ("Invoke");
-               internal static Type [] argsValueChange = { typeof (object), typeof (object), miInvokeValueChange.GetParameters () [1].ParameterType };
+               internal static Type [] argsBoundValueChange = { typeof (object), typeof (object), miInvokeValueChange.GetParameters () [1].ParameterType };
+               internal static Type [] argsValueChange = { typeof (object), miInvokeValueChange.GetParameters () [1].ParameterType };
                internal static FieldInfo fiNewValue = typeof (ValueChangeEventArgs).GetField ("NewValue");
                internal static FieldInfo fiMbName = typeof (ValueChangeEventArgs).GetField ("MemberName");
                internal static MethodInfo miValueChangeAdd = eiValueChange.GetAddMethod ();
@@ -69,12 +69,6 @@ namespace Crow
                        il.Emit (OpCodes.Ldarg_2);
                        il.Emit (OpCodes.Stfld, miSetCurIface);
                }
-               public static void emitBindingCreation(ILGenerator il, string memberName, string expression){
-                       il.Emit (OpCodes.Ldloc_0);
-                       il.Emit (OpCodes.Ldstr, memberName);
-                       il.Emit (OpCodes.Ldstr, expression);
-                       il.Emit (OpCodes.Callvirt, miAddBinding);
-               }
 
                public static void EmitSetValue(ILGenerator il, PropertyInfo pi, object val){
                        il.Emit (OpCodes.Ldloc_0);
@@ -267,7 +261,7 @@ namespace Crow
                                                MethodAttributes.Family | MethodAttributes.FamANDAssem | MethodAttributes.NewSlot,
                                                CallingConventions.Standard,
                                                typeof (void),
-                                               argsValueChange,
+                                               argsBoundValueChange,
                                                target_Type, true);
 
                                        il = dm.GetILGenerator (256);
index f9b58e008fc83f67808237fd1439ed2850ca6f56..2cdc2aef1e6e55641bc627ea832e837c45e019cb 100644 (file)
@@ -659,7 +659,7 @@ namespace Crow
                                string expression;
                                if (!getDefaultEvent(ei, styling, out expression))
                                        continue;
-                               CompilerServices.emitBindingCreation (il, ei.Name, expression);
+                               //CompilerServices.emitBindingCreation (il, ei.Name, expression);
                        }
 
                        foreach (PropertyInfo pi in thisType.GetProperties(BindingFlags.Public | BindingFlags.Instance)) {
index 44a9018bf24d3c94322c8b651982aed507daebab..e5d333742dbd96372b87ae38321ac90a2fe94c4a 100644 (file)
@@ -44,13 +44,15 @@ namespace Crow.IML
                //public SubNodeType curSubNodeType;
                public Stack<Node> nodesStack = new Stack<Node> ();
 
-               public Dictionary<string, string> Names = new Dictionary<string, string> ();
+               public Dictionary<string, List<NodeAddress>> Names  = new Dictionary<string, List<NodeAddress>>();
                public Dictionary<string, Dictionary<string, MemberAddress>> PropertyBindings = new Dictionary<string, Dictionary<string, MemberAddress>> ();
 
-               public Dictionary<NodeAddress, Dictionary<string, MemberAddress>> Bindings =
-                       new Dictionary<NodeAddress, Dictionary<string, MemberAddress>>();
-               public List<DataSourceBinding> DataSourceBindings = new List<DataSourceBinding>();
-
+               public Dictionary<NodeAddress, Dictionary<string, List<MemberAddress>>> Bindings =
+                       new Dictionary<NodeAddress, Dictionary<string, List<MemberAddress>>>();
+               //public List<DataSourceBinding> DataSourceBindings = new List<DataSourceBinding>();
+               public Dictionary<NamedNodeAddress, Dictionary<string, MemberAddress>> NamedBindings =
+                       new Dictionary<NamedNodeAddress, Dictionary<string, MemberAddress>>();
+               
                public Context (Type rootType)
                {
                        RootType = rootType;
index 89a293c3fe45321aeceec5baede9bafc7e01fb63..7f3c93daee5c51dcc65a32c397f9709b87ae3fbe 100644 (file)
@@ -30,9 +30,10 @@ namespace Crow.IML
        public struct MemberAddress
        {
                string memberName;
-               MemberInfo member;
+               public MemberInfo member;
                public NodeAddress Address;
 
+               public PropertyInfo Property { get { return member as PropertyInfo; }}
 //             public string Name {
 //                     get { return memberName; } 
 //                     set { memberName = value; }
index 9bc8f82a3ddce0c040490b2fa5578232185d7f32..a503a3bb8c165b6008bba1e9dd2f20e2b672e92c 100644 (file)
@@ -20,6 +20,8 @@
 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 using System;
 using System.Reflection;
+using System.Reflection.Emit;
+using System.Collections.Generic;
 
 namespace Crow.IML
 {
@@ -43,24 +45,19 @@ namespace Crow.IML
                #region Equality Compare
                public override bool Equals (object obj)
                {
-                       return obj is Node && this == (Node)obj;
+                       if (obj == null) 
+                               return false;                   
+                       Node n = (Node)obj;
+                       return CrowType == n.CrowType && Index == n.Index;
                }
                public override int GetHashCode ()
                {
                        return CrowType.GetHashCode () ^ Index.GetHashCode ();
                }
-               public static bool operator == (Node x, Node y)
-               {
-                       return x.CrowType == y.CrowType && x.Index == y.Index;
-               }
-               public static bool operator != (Node x, Node y)
-               {
-                       return !(x == y);
-               }
                #endregion
 
-               public bool IsTemplate {
-                       get { return typeof (TemplatedControl).IsAssignableFrom (CrowType) && Index == 0; }
+               public bool HasTemplate {
+                       get { return typeof (TemplatedControl).IsAssignableFrom (CrowType);}
                }
                public MethodInfo AddMethod {
                        get {
@@ -69,14 +66,36 @@ namespace Crow.IML
                                if (typeof (Container).IsAssignableFrom (CrowType))
                                        return CompilerServices.miSetChild;
                                if (typeof (TemplatedContainer).IsAssignableFrom (CrowType))
-                                       return Index == 0 ? CompilerServices.miLoadTmp : CompilerServices.miSetContent;
+                                       return Index < 0 ? CompilerServices.miLoadTmp : CompilerServices.miSetContent;
                                if (typeof (TemplatedGroup).IsAssignableFrom (CrowType))
-                                       return Index == 0 ? CompilerServices.miLoadTmp : CompilerServices.miAddItem;
+                                       return Index < 0 ? CompilerServices.miLoadTmp : CompilerServices.miAddItem;
                                if (typeof (TemplatedControl).IsAssignableFrom (CrowType))
                                        return CompilerServices.miLoadTmp;
                                return null;
                        }
                }
+               public void EmitGetInstance (ILGenerator il){
+                       if (typeof (Group).IsAssignableFrom (CrowType)) {
+                               il.Emit (OpCodes.Ldfld, typeof(Group).GetField ("children", BindingFlags.Instance | BindingFlags.NonPublic));
+                               il.Emit(OpCodes.Ldc_I4, Index);
+                               il.Emit (OpCodes.Callvirt, typeof(List<GraphicObject>).GetMethod("get_Item", new Type[] { typeof(Int32) }));
+                               return;
+                       }
+                       if (typeof(Container).IsAssignableFrom (CrowType) || Index < 0) {
+                               il.Emit (OpCodes.Ldfld, typeof(PrivateContainer).GetField ("child", BindingFlags.Instance | BindingFlags.NonPublic));
+                               return;
+                       }
+                       if (typeof(TemplatedContainer).IsAssignableFrom (CrowType)) {
+                               il.Emit (OpCodes.Callvirt, typeof(TemplatedContainer).GetProperty ("Content").GetGetMethod ());
+                               return;
+                       }
+                       if (typeof(TemplatedGroup).IsAssignableFrom (CrowType)) {
+                               il.Emit (OpCodes.Callvirt, typeof(TemplatedGroup).GetProperty ("Items").GetGetMethod ());
+                               il.Emit(OpCodes.Ldc_I4, Index);
+                               il.Emit (OpCodes.Callvirt, typeof(List<GraphicObject>).GetMethod("get_Item", new Type[] { typeof(Int32) }));
+                               return;
+                       }
+               }
 
                public static implicit operator string (Node sn)
                {
index 12ecec38c4e8bc3c58312030527e727faf21032d..b7517b1f5c15ae7a814b56c67ef7ce47dff9a1f4 100644 (file)
@@ -28,9 +28,16 @@ namespace Crow.IML
        {
                public NodeAddress (Node[] nodes) : base(nodes) { 
                }
+
+               public Type NodeType { get { return this[this.Count -1].CrowType; }}
+
                public override bool Equals (object obj)
                {
-                       return obj is NodeAddress && this == obj as NodeAddress;
+                       if (obj == null) 
+                               return false;
+                       
+                       NodeAddress na = (NodeAddress)obj;
+                       return this.SequenceEqual (na);
                }
                public override int GetHashCode ()
                {
@@ -41,21 +48,20 @@ namespace Crow.IML
                                return hash;
                        }
                }
-               public static bool operator == (NodeAddress x, NodeAddress y)
-               {
-                       return x.SequenceEqual (y);
-               }
-               public static bool operator != (NodeAddress x, NodeAddress y)
-               {
-                       return !(x == y);
-               }
 
                public override string ToString ()
                {
                        string tmp = "";
                        foreach (Node n in this)
-                               tmp += string.Format ("{0}[{1}];", n.CrowType.Name, n.Index);                   
+                               tmp += string.Format ("{0};", n.Index);                 
                        return tmp;
                }
        }
+
+       public class NamedNodeAddress : NodeAddress {
+               public string Name;
+               public NamedNodeAddress(string name, Node[] nodes) : base(nodes){
+                       Name = name;
+               }
+       }
 }
index 0bd332780f1cf5c44fa58256367c9a7e9a1636d8..e6924447b48b722f43da1471d39145ec401cb628 100644 (file)
@@ -85,7 +85,8 @@ namespace Crow
 
                List<DynamicMethod> dsValueChangedDynMeths = new List<DynamicMethod>();
                List<Delegate> dataSourceChangedDelegates = new List<Delegate>();
-
+               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
                #region IML parsing
                /// <summary>
                /// Parses IML and build a dynamic method that will be used to instanciate one or multiple occurence of the IML file or fragment
@@ -132,7 +133,7 @@ namespace Crow
 
                        ctx.il.Emit (OpCodes.Ldloc_0);//save current go onto the stack if child has to be added
 
-                       if (ctx.CurrentNode.IsTemplate)
+                       if (ctx.CurrentNode.HasTemplate)
                                emitTemplateLoad (ctx, tmpXml);
 
                        emitGOLoad (ctx, tmpXml);
@@ -140,6 +141,7 @@ namespace Crow
                        ctx.il.Emit (OpCodes.Pop);//pop saved ref to current object
                }
                void emitTemplateLoad (Context ctx, string tmpXml) {
+                       ctx.CurrentNode.Index--;//template indexing use -1
                        //if its a template, first read template elements
                        using (XmlTextReader reader = new XmlTextReader (tmpXml, XmlNodeType.Element, null)) {
                                List<string []> itemTemplateIds = new List<string []> ();
@@ -248,23 +250,22 @@ namespace Crow
                                                if (mi == null)
                                                        throw new Exception ("Member '" + reader.Name + "' not found in " + ctx.CurrentNode.CrowType.Name);
                                                if (mi.MemberType == MemberTypes.Event) {
-                                                       CompilerServices.emitBindingCreation (ctx.il, reader.Name, reader.Value);
+                                                       //CompilerServices.emitBindingCreation (ctx.il, reader.Name, reader.Value);
                                                        continue;
                                                }
                                                PropertyInfo pi = mi as PropertyInfo;
                                                if (pi == null)
                                                        throw new Exception ("Member '" + reader.Name + "' not found in " + ctx.CurrentNode.CrowType.Name);
 
-                                               //if (pi.Name == "Name")
-                                               //      ctx.Names.Add (reader.Value, Node.AddressToString (ctx.nodesStack.ToArray ()));
-
-                                               if (reader.Value.StartsWith ("{", StringComparison.OrdinalIgnoreCase)) {
-                                                       
-
+                                               if (pi.Name == "Name"){
+                                                       if (!ctx.Names.ContainsKey(reader.Value))
+                                                               ctx.Names[reader.Value] = new List<NodeAddress>();                                                      
+                                                       ctx.Names[reader.Value].Add(ctx.CurrentNodeAddress);
+                                               }
+                                               
+                                               if (reader.Value.StartsWith ("{", StringComparison.OrdinalIgnoreCase))
                                                        readPropertyBinding (ctx, reader.Name, reader.Value.Substring (1, reader.Value.Length - 2));
-
-                                                       //CompilerServices.emitBindingCreation (reader.il, reader.Name, reader.Value.Substring (1, reader.Value.Length - 2));
-                                               } else
+                                               else
                                                        CompilerServices.EmitSetValue (ctx.il, pi, reader.Value);
 
                                        }
@@ -280,6 +281,8 @@ namespace Crow
                                ctx.nodesStack.Push (ctx.CurrentNode);
                                readChildren (reader, ctx);
                                ctx.nodesStack.Pop ();
+
+                               emitCheckAndBindValueChanged (ctx);
                        }
                }
                /// <summary>
@@ -338,6 +341,29 @@ namespace Crow
                }
                #endregion
 
+
+               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
+
+                       //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.Call, 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);
+
+                       ctx.il.MarkLabel (labContinue);
+               }
                /// <summary>
                /// Tries the find target.
                /// </summary>
@@ -360,64 +386,62 @@ namespace Crow
                                twoWay = true;
                        }
 
-                       string [] bindingExp = expression.Split ('/');
+                       string[] bindingExp = expression.Split ('/');
 
                        if (bindingExp.Length == 1) {
                                //datasource binding
-                               processDataSourceBinding(ctx, sourceMember, bindingExp [0]);
+                               processDataSourceBinding (ctx, sourceMember, bindingExp [0]);
+                               return;
+                       }
 
+                       NodeAddress currentNode = ctx.CurrentNodeAddress;
+                       int ptr = currentNode.Count - 1;
+
+                       //if exp start with '/' => Graphic tree parsing start at source
+                       if (string.IsNullOrEmpty (bindingExp [0])) {
+                               //TODO:
+                       } else if (bindingExp [0] == ".") { //search template root
+                               while (ptr > 0) {
+                                       ptr--;
+                                       if (typeof(TemplatedControl).IsAssignableFrom (currentNode [ptr].CrowType))
+                                               break;
+                               }
+                       } else if (bindingExp [0] == "..") { //search starting at current node
+                               int levelUp = bindingExp.Length - 1;
+                               if (levelUp > ptr)
+                                       throw new Exception ("Binding error: try to bind outside IML source");
+                               ptr -= levelUp;
                        }
-//                     else {
-//                             int ptr = 0;
-//
-//                             //if exp start with '/' => Graphic tree parsing start at source
-//                             if (string.IsNullOrEmpty (bindingExp [0]))
-//                                     ptr++;
-//                             else if (bindingExp[0] == "."){ //search template root
-//                                     do {
-//                                             target = new NodeAddress(ctx.
-//                                             if (tmpTarget == null)
-//                                                     return false;
-//                                             if (tmpTarget is Interface)
-//                                                     throw new Exception ("Not in Templated Control");
-//                                     } while (!(tmpTarget is TemplatedControl));
-//                                     ptr++;
-//                             }
-//                             while (ptr < bindingExp.Length - 1) {
-//                                     if (tmpTarget == null) {
-//                                             #if DEBUG_BINDING
-//                                             Debug.WriteLine ("\tTarget not found => " + this.ToString());
-//                                             #endif
-//                                             return false;
-//                                     }
-//                                     if (bindingExp [ptr] == "..")
-//                                             tmpTarget = tmpTarget.LogicalParent;
-//                                     else if (bindingExp [ptr] == ".") {
-//                                             if (ptr > 0)
-//                                                     throw new Exception ("Syntax error in binding, './' may only appear in first position");
-//                                             tmpTarget = Source.Instance as ILayoutable;
-//                                     } else
-//                                             tmpTarget = (tmpTarget as GraphicObject).FindByName (bindingExp [ptr]);
-//                                     ptr++;
-//                             }
-//
-//                             if (tmpTarget == null) {
-//                                     #if DEBUG_BINDING
-//                                     Debug.WriteLine ("\tBinding Target not found => " + this.ToString());
-//                                     #endif
-//                                     return false;
-//                             }
-//
-//                             string [] bindTrg = bindingExp [ptr].Split ('.');
-//
-//                             if (bindTrg.Length == 1)
-//                                     memberName = bindTrg [0];
-//                             else if (bindTrg.Length == 2) {
-//                                     tmpTarget = (tmpTarget as GraphicObject).FindByName (bindTrg [0]);
-//                                     memberName = bindTrg [1];
-//                             } else
-//                                     throw new Exception ("Syntax error in binding, expected 'go dot member'");
-//
+                       Node[] targetNode = new Node[ptr+1];
+                       Array.Copy (currentNode.ToArray (), targetNode, ptr + 1);
+                       NodeAddress targetNA = new NodeAddress (targetNode);
+
+                       string [] bindTrg = bindingExp [currentNode.Count - 1 - ptr].Split ('.');
+
+                       if (bindTrg.Length == 1)
+                               memberName = bindTrg [0];
+                       else if (bindTrg.Length == 2) {
+                               //named target
+                               //TODO:
+
+                               memberName = bindTrg [1];
+                               return;
+                       } else
+                               throw new Exception ("Syntax error in binding, expected 'go dot member'");
+
+                       Dictionary<string, List<MemberAddress>> nodeBindings = null;
+                       if (ctx.Bindings.ContainsKey (targetNA))
+                               nodeBindings = ctx.Bindings [targetNA];
+                       else {
+                               nodeBindings = new Dictionary<string, List<MemberAddress>> ();
+                               ctx.Bindings [targetNA] = nodeBindings;
+                       }
+
+                       if (!nodeBindings.ContainsKey (memberName))
+                               nodeBindings [memberName] = new List<MemberAddress> ();
+                       nodeBindings [memberName].Add (new MemberAddress (currentNode, sourceMember));
+
+                       //
 //                             if (tmpTarget == null) {
 //                                     #if DEBUG_BINDING
 //                                     Debug.WriteLine ("\tBinding Target not found => " + this.ToString());
@@ -441,12 +465,14 @@ namespace Crow
                        Debug.WriteLine ("Property less binding: " + Target + expression);
                        #endif
                }
-
+               /// <summary>
+               /// create the valuechanged handler, the datasourcechanged handler and emit event handling
+               /// </summary>
                void processDataSourceBinding(Context ctx, string sourceMember, string dataSourceMember){
                        #region create valuechanged method
                        DynamicMethod dm = new DynamicMethod ("dyn_valueChanged",
                                typeof (void),
-                               CompilerServices.argsValueChange, true);
+                               CompilerServices.argsBoundValueChange, true);
 
                        ILGenerator il = dm.GetILGenerator (256);
 
@@ -476,6 +502,9 @@ namespace Crow
                        PropertyInfo piSource = ctx.CurrentNode.CrowType.GetProperty(sourceMember);
                        Type sourceValueType = piSource.PropertyType;
 
+                       //il.Emit (OpCodes.Call, typeof(object).GetMethod("GetType"));
+                       //il.Emit (OpCodes.Call, typeof(Type).GetProperty("IsValueType").GetGetMethod());
+
                        if (sourceValueType == typeof (string)) {
                                il.Emit (OpCodes.Callvirt, CompilerServices.miObjToString);
                        } else if (!sourceValueType.IsValueType)
@@ -486,8 +515,6 @@ namespace Crow
                                il.Emit (OpCodes.Unbox_Any, sourceValueType);
 
                        il.Emit (OpCodes.Callvirt, piSource.GetSetMethod ());
-                       //il.Emit (OpCodes.Pop);
-                       //il.Emit (OpCodes.Pop);
 
                        il.MarkLabel (endMethod);
 
@@ -510,57 +537,38 @@ namespace Crow
                                CompilerServices.argsDSChange, true);
 
                        il = dm.GetILGenerator (256);
-                       //il.DeclareLocal (typeof(Object[]));
 
                        il.Emit (OpCodes.Nop);
 
-//                     //load new datasource onto the stack for handler addition at the end
+                       //load new datasource onto the stack for handler addition at the end
                        il.Emit (OpCodes.Ldarg_2);
                        il.Emit (OpCodes.Ldfld, CompilerServices.fiDSCNewDS);
 
-                       #region Load cached delegate
+                       //first we have to create delegate from cached dynMethod bound to the GraphicObject currently instanced
+
+                       //Load cached delegate
                        il.Emit(OpCodes.Ldarg_0);//load ref to this instanciator onto the stack
                        il.Emit(OpCodes.Ldfld, typeof(Instantiator).GetField("dsValueChangedDynMeths", BindingFlags.Instance | BindingFlags.NonPublic));
-                       il.Emit(OpCodes.Ldc_I4, dmVC);
+                       il.Emit(OpCodes.Ldc_I4, dmVC);//load index of dynmathod
                        il.Emit(OpCodes.Callvirt, typeof(List<DynamicMethod>).GetMethod("get_Item", new Type[] { typeof(Int32) }));
-                       #endregion
 
                        //load ds changed eventhandlertype
                        il.Emit(OpCodes.Ldtoken, typeof(EventHandler<ValueChangeEventArgs>));
                        il.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle", new
                                Type[1]{typeof(RuntimeTypeHandle)}));
-                       //typeof (GraphicObject).GetEvent ("DataSourceChanged").EventHandlerType;
-                       //il.Emit(OpCodes.Ldfld, typeof(CompilerServices).GetField("ehTypeDSChange", BindingFlags.Static | BindingFlags.NonPublic););
 
-                       //create object[] for delegate creation parameters
-//                     il.Emit (OpCodes.Ldc_I4_1);
-//                     il.Emit (OpCodes.Newarr, typeof(object));
-//                     il.Emit (OpCodes.Stloc_0);//save array ref
-//                     il.Emit (OpCodes.Ldloc_0);//load array ref onto the stack
-//                     il.Emit (OpCodes.Ldc_I4_0);//0 is the index of the dm in the array
-
-                       //load datasource change source
-                       il.Emit (OpCodes.Ldarg_1);
-                       //il.Emit (OpCodes.Ldfld, CompilerServices.fiDSCNewDS);
-
-                       //create bound delegate
-                       il.Emit (OpCodes.Call, CompilerServices.miCreateBoundDelegate);
-                       //set delegete as index 0 in the object array
-//                     il.Emit(OpCodes.Ldelem_I4);
+                       il.Emit (OpCodes.Ldarg_1);//load datasource change source
+                       il.Emit (OpCodes.Call, CompilerServices.miCreateBoundDelegate);//create bound delegate
 
                        //add new delegate to datasource valuechanged event
                        il.Emit(OpCodes.Callvirt, typeof(IValueChange).GetEvent("ValueChanged").AddMethod);//call add event                     //il.Emit(OpCodes.Pop);
-                       //il.Emit(OpCodes.Pop);
-                       //il.Emit(OpCodes.Pop);
-                       //il.Emit(OpCodes.Pop);
                        il.Emit (OpCodes.Ret);
 
-
-                       #endregion
-
+                       //store dschange delegate in instatiator instance for access while instancing graphic object
                        int delDSIndex = dataSourceChangedDelegates.Count;
                        Delegate del = dm.CreateDelegate (CompilerServices.ehTypeDSChange, this);
                        dataSourceChangedDelegates.Add(del);
+                       #endregion
 
                        #region Emit datasourcechanged handler binding in the loader context
                        ctx.il.Emit(OpCodes.Ldloc_0);//load ref to current graphic object
@@ -568,12 +576,111 @@ namespace Crow
                        ctx.il.Emit(OpCodes.Ldfld, typeof(Instantiator).GetField("dataSourceChangedDelegates", BindingFlags.Instance | BindingFlags.NonPublic));
                        ctx.il.Emit(OpCodes.Ldc_I4, delDSIndex);//load delegate index
                        ctx.il.Emit(OpCodes.Callvirt, typeof(List<DynamicMethod>).GetMethod("get_Item", new Type[] { typeof(Int32) }));
-
                        ctx.il.Emit(OpCodes.Callvirt, typeof(GraphicObject).GetEvent("DataSourceChanged").AddMethod);//call add event
                        #endregion
-                       //miValueChangeAdd.Invoke (grouped [0].Target.Instance, new object [] { del });
                }
-                       
+
+               /// <summary>
+               /// Create and store in the instanciator the ValueChanged delegates
+               /// those delegates uses grtree functions to set destination value so they don't
+               /// need to be bound to destination instance as in the ancient system.
+               /// </summary>
+               void emitBindingDelegates(Context ctx){
+                       foreach (KeyValuePair<NodeAddress,Dictionary<string, List<MemberAddress>>> bindings in ctx.Bindings ) { 
+
+                               Type origineNodeType = bindings.Key.NodeType;
+
+                               //value changed dyn method
+                               DynamicMethod dm = new DynamicMethod ("dyn_valueChanged",
+                                       typeof (void), CompilerServices.argsValueChange, true);
+
+                               ILGenerator il = dm.GetILGenerator (256);
+
+                               System.Reflection.Emit.Label [] jumpTable = 
+                                       new System.Reflection.Emit.Label [bindings.Value.Count];
+                               System.Reflection.Emit.Label endMethod = il.DefineLabel ();
+
+                               il.DeclareLocal (typeof(object));
+
+                               il.Emit (OpCodes.Nop);
+                               il.Emit (OpCodes.Ldarg_0);//load source instance of ValueChanged event
+
+                               //load source member name
+                               il.Emit (OpCodes.Ldarg_1);
+                               il.Emit (OpCodes.Ldfld, typeof(ValueChangeEventArgs).GetField ("MemberName"));
+
+                               int i = 0;
+                               foreach (KeyValuePair<string, List<MemberAddress>> bindingCase in bindings.Value ) {
+                                       Type origineType = origineNodeType.GetProperty (bindingCase.Key).PropertyType;
+
+                                       jumpTable [i] = il.DefineLabel ();
+                                       #region member name test
+                                       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, jumpTable [i]);//if not equal, jump to next case
+                                       #endregion
+
+                                       #region destination member affectations
+                                       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 origine = bindings.Key;
+                                               NodeAddress destination = ma.Address;
+
+                                               if (origine.Count < destination.Count){
+                                                       for (int j = origine.Count; j < destination.Count; j++)
+                                                               destination[j].EmitGetInstance(il);
+                                               }else{
+                                                       for (int j = destination.Count; j < origine.Count; j++)
+                                                               il.Emit(OpCodes.Callvirt, typeof(ILayoutable).GetProperty("Parent").GetGetMethod());
+                                               }
+                                               //load new value
+                                               System.Reflection.Emit.Label labValueType = il.DefineLabel ();
+                                               il.Emit (OpCodes.Ldarg_1);
+                                               il.Emit (OpCodes.Ldfld, typeof (ValueChangeEventArgs).GetField ("NewValue"));
+
+                                               emitConvert(il,origineType, ma.Property.PropertyType);
+
+                                               //set value
+                                               il.Emit (OpCodes.Callvirt, ma.Property.GetSetMethod());
+
+                                               il.Emit (OpCodes.Br, endMethod);
+                                               il.MarkLabel (jumpTable [i]);
+                                       }
+                                       #endregion
+
+                                       i++;
+                               }
+                               il.MarkLabel (endMethod);
+                               il.Emit (OpCodes.Ret);
+
+                               bindingDelegates [bindings.Key.ToString()] = dm.CreateDelegate (typeof(EventHandler<ValueChangeEventArgs>));
+                       }
+               }
+               void emitConvert(ILGenerator il, Type origType, Type destType){                 
+                       if (destType == typeof (string))
+                               il.Emit (OpCodes.Callvirt, CompilerServices.miObjToString);
+                       else if (origType.IsValueType) {
+                               if (destType != origType)
+                                       il.Emit (OpCodes.Callvirt, CompilerServices.GetConvertMethod (destType));
+                               else
+                                       il.Emit (OpCodes.Unbox_Any, destType);
+                       }else
+                               il.Emit (OpCodes.Castclass, destType);
+               }
+               void emitConvertWorking(ILGenerator il, Type sourceValueType){
+                       if (sourceValueType == typeof (string)) {
+                               il.Emit (OpCodes.Callvirt, CompilerServices.miObjToString);
+                       } else if (!sourceValueType.IsValueType)
+                               il.Emit (OpCodes.Castclass, sourceValueType);
+                       else if (sourceValueType != sourceValueType) {
+                               il.Emit (OpCodes.Callvirt, CompilerServices.GetConvertMethod (sourceValueType));
+                       } else
+                               il.Emit (OpCodes.Unbox_Any, sourceValueType);                   
+               }
                //public string GetImlSourcesCode(){
                //      try {
                //              using (StreamReader sr = new StreamReader (imlPath))