]> O.S.I.I.S - jp/crow.git/commitdiff
split CompilerServices objects in separate files, uid for GO even while not debugging
authorjpbruyere <jp.bruyere@hotmail.com>
Wed, 1 Jun 2016 09:59:40 +0000 (11:59 +0200)
committerjpbruyere <jp.bruyere@hotmail.com>
Wed, 1 Jun 2016 09:59:40 +0000 (11:59 +0200)
Crow.csproj
Tests/Tests.csproj
src/CompilerServices/Bindings.cs [new file with mode: 0644]
src/CompilerServices/CompilerServices.cs
src/CompilerServices/MemberReference.cs [new file with mode: 0644]
src/GraphicObjects/GraphicObject.cs
src/GraphicObjects/IBindable.cs

index 4b108538a2092806b87b9e6fd8905af4ecba16c8..db122bb86fb6b57a0e3560705db5fb1289e20f7d 100644 (file)
     <Compile Include="src\Measure.cs">
       <LogicalName></LogicalName>
     </Compile>
+    <Compile Include="src\CompilerServices\MemberReference.cs" />
+    <Compile Include="src\CompilerServices\Bindings.cs" />
   </ItemGroup>
   <ItemGroup>
     <Reference Include="System" />
index 444c63c86bfd0eef6f4b104129ea94ff0dfcaccc..0a839765b9bd12db5ae53faa115fc58301d2b3af 100644 (file)
     <None Include="GOLIBTestsOTK.cs">
       <LogicalName></LogicalName>
     </None>
-    <None Include="Interfaces\Divers\2 %28copier%29.crow">
-      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
-      <LogicalName></LogicalName>
-    </None>
   </ItemGroup>
   <ItemGroup>
     <Folder Include="Interfaces\" />
diff --git a/src/CompilerServices/Bindings.cs b/src/CompilerServices/Bindings.cs
new file mode 100644 (file)
index 0000000..5931bb8
--- /dev/null
@@ -0,0 +1,199 @@
+//
+//  Bindings.cs
+//
+//  Author:
+//       Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+//  Copyright (c) 2016 jp
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+using System;
+using System.Diagnostics;
+
+namespace Crow
+{
+       /// <summary>
+       /// Binding Class
+       /// </summary>
+       public class Binding
+       {
+               static int bindingCpt;
+               string dynMethodId = "";
+               bool resolved;
+
+               public bool TwoWayBinding;
+               public MemberReference Target;
+               public MemberReference Source;
+
+               public string Expression;
+
+               public string DynMethodId {
+                       get { return dynMethodId; }
+               }
+
+               public bool Resolved {
+                       get { return resolved; }
+                       set {
+                               if (value == resolved)
+                                       return;
+#if DEBUG_BINDING
+                               if (value == true)
+                                       Debug.WriteLine ("\tOk => " + this.ToString());
+                               else
+                                       Debug.WriteLine ("\tresolved state reseted => " + this.ToString());
+#endif
+                               resolved = value;
+                       }
+               }
+
+               #region CTOR
+               public Binding () { }
+               public Binding (MemberReference _target, string _expression)
+               {
+                       Target = _target;
+                       Expression = _expression;
+               }
+               public Binding (object _target, string _member, string _expression)
+               {
+                       Target = new MemberReference (_target, _target.GetType ().GetMember (_member) [0]);
+                       Expression = _expression;
+               }
+               public Binding (object _target, string _targetMember, object _source, string _sourceMember)
+               {
+                       Target = new MemberReference (_target, _target.GetType ().GetMember (_targetMember) [0]);
+                       Source = new MemberReference (_source, _source.GetType ().GetMember (_sourceMember) [0]);
+               }
+               public Binding (MemberReference _target, MemberReference _source)
+               {
+                       Target = _target;
+                       Source = _source;
+               }
+               #endregion
+
+               public string CreateNewDynMethodId ()
+               {
+                       if (!string.IsNullOrEmpty (dynMethodId))
+                               return dynMethodId;
+                       dynMethodId = "dynHandle_" + bindingCpt;
+                       bindingCpt++;
+                       return dynMethodId;
+               }
+
+               public bool FindSource ()
+               {
+                       if (Source != null)
+                               return true;
+
+                       string member = null;
+
+                       //if binding exp = '{}' => binding is done on datasource
+                       if (string.IsNullOrEmpty (Expression)) {
+                               Object o = (Target.Instance as GraphicObject).DataSource;
+                               if (o == null)
+                                       return false;
+                               Source = new MemberReference (o);
+                               return true;
+                       }
+
+                       string expression = Expression;
+
+                       if (expression.StartsWith ("²")) {
+                               expression = expression.Substring (1);
+                               TwoWayBinding = true;
+                       }
+
+                       string [] bindingExp = expression.Split ('/');
+
+                       if (bindingExp.Length == 1) {
+                               //datasource binding
+                               Source = new MemberReference ((Target.Instance as GraphicObject).DataSource);
+                               member = bindingExp [0];
+                       } else {
+                               int ptr = 0;
+                               ILayoutable tmp = Target.Instance as ILayoutable;
+                               if (string.IsNullOrEmpty (bindingExp [0])) {
+                                       //if exp start with '/' => Graphic tree parsing start at top container
+                                       tmp = Interface.CurrentInterface as ILayoutable;
+                                       ptr++;
+                               }
+                               while (ptr < bindingExp.Length - 1) {
+                                       if (tmp == null) {
+#if DEBUG_BINDING
+                                               Debug.WriteLine ("\tERROR: target not found => " + this.ToString());
+#endif
+                                               return false;
+                                       }
+                                       if (bindingExp [ptr] == "..")
+                                               tmp = tmp.LogicalParent;
+                                       else if (bindingExp [ptr] == ".") {
+                                               if (ptr > 0)
+                                                       throw new Exception ("Syntax error in binding, './' may only appear in first position");
+                                               tmp = Target.Instance as ILayoutable;
+                                       } else
+                                               tmp = (tmp as GraphicObject).FindByName (bindingExp [ptr]);
+                                       ptr++;
+                               }
+
+                               if (tmp == null) {
+#if DEBUG_BINDING
+                                       Debug.WriteLine ("\tERROR: target not found => " + this.ToString());
+#endif
+                                       return false;
+                               }
+
+                               string [] bindTrg = bindingExp [ptr].Split ('.');
+
+                               if (bindTrg.Length == 1)
+                                       member = bindTrg [0];
+                               else if (bindTrg.Length == 2) {
+                                       tmp = (tmp as GraphicObject).FindByName (bindTrg [0]);
+                                       member = bindTrg [1];
+                               } else
+                                       throw new Exception ("Syntax error in binding, expected 'go dot member'");
+
+                               Source = new MemberReference (tmp);
+                       }
+                       if (Source == null) {
+                               Debug.WriteLine ("Binding Source is null: " + Expression);
+                               return false;
+                       }
+
+                       if (Source.TryFindMember (member)) {
+                               if (TwoWayBinding) {
+                                       IBindable source = Source.Instance as IBindable;
+                                       if (source == null)
+                                               throw new Exception (Target.Instance + " does not implement IBindable for 2 way bindings");
+                                       source.Bindings.Add (new Binding (Source, Target));
+                               }
+                               return true;
+                       }
+
+                       Debug.WriteLine ("Binding member not found: " + member);
+                       Source = null;
+                       return false;
+               }
+               public void Reset ()
+               {
+                       Source = null;
+                       dynMethodId = "";
+                       Resolved = false;
+               }
+               public override string ToString ()
+               {
+                       return string.Format ("[Binding: {0}.{1} <= {2}]", Target.Instance, Target.Member.Name, Expression);
+               }
+       }
+
+}
+
index 0f8c5d474fef5452f4186407802b4a78fa9bd871..71f119e277d67e5a9c23bf503d7ece605581427d 100644 (file)
@@ -1,7 +1,6 @@
 using System;
 using System.Reflection.Emit;
 using System.Reflection;
-using System.Collections;
 using System.Diagnostics;
 using System.Linq;
 using System.Collections.Generic;
@@ -10,254 +9,46 @@ using System.Runtime.CompilerServices;
 
 namespace Crow
 {
-       public class MemberReference
-       {
-               public object Instance;
-               public MemberInfo Member;
-
-               public PropertyInfo Property { get { return Member as PropertyInfo; } }
-               public FieldInfo Field { get { return Member as FieldInfo; } }
-               public EventInfo Event { get { return Member as EventInfo; } }
-               public MethodInfo Method { get { return Member as MethodInfo; } }
-
-               public MemberReference(){
-               }
-               public MemberReference(object _instance, MemberInfo _member = null)
-               {
-                       Instance = _instance;
-                       Member = _member;
-               }
-               public bool FindMember(string _memberName)
-               {
-                       if (Instance == null)
-                               return false;
-                       Type t = Instance.GetType ();
-                       Member = t.GetMember (_memberName,BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance).FirstOrDefault ();
-
-                       #region search for extensions methods if member not found in type
-                       if (Member == null && !string.IsNullOrEmpty(_memberName))
-                       {
-                               Assembly a = Assembly.GetExecutingAssembly();
-                               Member =  CompilerServices.GetExtensionMethods(a, t).Where(em=>em.Name == _memberName).FirstOrDefault();
-                       }                       
-                       #endregion
-               
-                       return string.IsNullOrEmpty(_memberName) ? false : true;
-               }
-       }
-       public class Binding{
-               static int bindingCpt;
-               string dynMethodId = "";
-               bool resolved;
-
-               public bool TwoWayBinding;
-
-               public string NewDynMethodId {
-                       get {
-                               if (!string.IsNullOrEmpty (dynMethodId))
-                                       return dynMethodId;
-                               dynMethodId = "dynHandle_" + bindingCpt;
-                               bindingCpt++;
-                               return dynMethodId;
-                       }
-               }
-               public string DynMethodId {
-                       get { return dynMethodId; }
-               }
-
-
-               public bool Resolved {
-                       get {
-                               return resolved;
-                       }
-                       set {
-                               if (value == resolved)
-                                       return;
-                               #if DEBUG_BINDING
-                               if (value == true)
-                                       Debug.WriteLine ("\tOk => " + this.ToString());
-                               else
-                                       Debug.WriteLine ("\tresolved state reseted => " + this.ToString());
-                               #endif
-                               resolved = value;
-                       }
-               }
-
-               public MemberReference Target;
-               public MemberReference Source;
-
-               public string Expression;
-
-               #region CTOR
-               public Binding(){}
-               public Binding(MemberReference _target, string _expression)
-               {
-                       Target = _target;
-                       Expression = _expression;
-               }
-               public Binding(object _target, string _member, string _expression)
-               {
-                       Target = new MemberReference (_target, _target.GetType().GetMember (_member) [0]);
-                       Expression = _expression;
-               }
-               public Binding(object _target, string _targetMember, object _source, string _sourceMember)
-               {
-                       Target = new MemberReference (_target, _target.GetType().GetMember (_targetMember) [0]);
-                       Source = new MemberReference (_source, _source.GetType().GetMember (_sourceMember) [0]);
-               }
-               public Binding(MemberReference _target, MemberReference _source)
-               {
-                       Target = _target;
-                       Source = _source;
-               }
-               #endregion
-
-               public bool FindSource(){
-                       if (Source != null)
-                               return true;
-                       
-                       string member = null;
-
-                       //if binding exp = '{}' => binding is done on datasource
-                       if (string.IsNullOrEmpty (Expression)) {
-                               Object o = (Target.Instance as GraphicObject).DataSource;
-                               if (o == null)
-                                       return false;
-                               Source = new MemberReference (o);
-                               return true;
-                       }
-
-                       string expression = Expression;
-
-                       if (Expression.StartsWith ("²")) {
-                               expression = expression.Substring (1);
-                               TwoWayBinding = true;
-                       }
-
-                       string[] bindingExp = expression.Split ('/');
-
-                       if (bindingExp.Length == 1) {
-                               //datasource binding
-                               Source = new MemberReference((Target.Instance as GraphicObject).DataSource);
-                               member = bindingExp [0];
-                       } else {
-                               int ptr = 0;
-                               ILayoutable tmp = Target.Instance as ILayoutable;
-                               if (string.IsNullOrEmpty (bindingExp [0])) {
-                                       //if exp start with '/' => Graphic tree parsing start at top container
-                                       tmp = Interface.CurrentInterface as ILayoutable;
-                                       ptr++;
-                               }
-                               while (ptr < bindingExp.Length - 1) {
-                                       if (tmp == null) {
-                                               #if DEBUG_BINDING
-                                               Debug.WriteLine ("\tERROR: target not found => " + this.ToString());
-                                               #endif
-                                               return false;
-                                       }
-                                       if (bindingExp [ptr] == "..")
-                                               tmp = tmp.LogicalParent;
-                                       else if (bindingExp [ptr] == ".") {
-                                               if (ptr > 0)
-                                                       throw new Exception ("Syntax error in binding, './' may only appear in first position");                                                
-                                               tmp = Target.Instance as ILayoutable;
-                                       }else
-                                               tmp = (tmp as GraphicObject).FindByName (bindingExp [ptr]);
-                                       ptr++;
-                               }
-
-                               if (tmp == null) {
-                                       #if DEBUG_BINDING
-                                       Debug.WriteLine ("\tERROR: target not found => " + this.ToString());
-                                       #endif
-                                       return false;
-                               }
-
-                               string[] bindTrg = bindingExp [ptr].Split ('.');
-
-                               if (bindTrg.Length == 1)
-                                       member = bindTrg [0];
-                               else if (bindTrg.Length == 2){
-                                       tmp = (tmp as GraphicObject).FindByName (bindTrg [0]);
-                                       member = bindTrg [1];
-                               } else
-                                       throw new Exception ("Syntax error in binding, expected 'go dot member'");
-
-                               Source = new MemberReference(tmp);
-                       }
-                       if (Source == null) {
-                               Debug.WriteLine ("Binding Source is null: " + Expression);
-                               return false;
-                       }
-
-                       if (Source.FindMember (member)) {
-                               if (TwoWayBinding) {
-                                       IBindable source = Source.Instance as IBindable;
-                                       if (source == null)
-                                               throw new Exception (Target.Instance + " does not implement IBindable for 2 way bindings");
-                                       source.Bindings.Add (new Binding (Source, Target));
-                               }
-                               return true;
-                       }
-                       
-                       Debug.WriteLine ("Binding member not found: " + member);
-                       Source = null;
-                       return false;
-               }
-               public void Reset()
-               {
-                       Source = null;
-                       dynMethodId = "";
-                       Resolved = false;
-               }
-               public override string ToString ()
-               {
-                       return string.Format ("[Binding: {0}.{1} <= {2}]", Target.Instance, Target.Member.Name, Expression);
-               }
-       }
-
-
-
        public static class CompilerServices
        {
-               public static void ResolveBindings(List<Binding> Bindings)
+               public static void ResolveBindings (List<Binding> Bindings)
                {
                        if (Bindings == null)
                                return;
                        if (Bindings.Count == 0)
                                return;
-//#if DEBUG_BINDING
-//                     Debug.WriteLine ("Resolve Bindings => " + this.ToString ());
-//#endif
+                       //#if DEBUG_BINDING
+                       //                      Debug.WriteLine ("Resolve Bindings => " + this.ToString ());
+                       //#endif
                        //grouped bindings by Instance of Source
-                       Dictionary<object,List<Binding>> resolved = new Dictionary<object, List<Binding>>();
+                       Dictionary<object, List<Binding>> resolved = new Dictionary<object, List<Binding>> ();
 
                        foreach (Binding b in Bindings) {
                                if (b.Resolved)
                                        continue;
                                if (b.Target.Member.MemberType == MemberTypes.Event) {
-                                       if (b.Expression.StartsWith("{")){
-                                               CompilerServices.CompileEventSource(b);
+                                       if (b.Expression.StartsWith ("{")) {
+                                               CompilerServices.CompileEventSource (b);
                                                continue;
                                        }
                                        if (!b.FindSource ())
                                                continue;
                                        //register handler for event
                                        if (b.Source.Method == null) {
-                                               Debug.WriteLine ("\tError: Handler Method not found: " + b.ToString());
+                                               Debug.WriteLine ("\tError: Handler Method not found: " + b.ToString ());
                                                continue;
                                        }
                                        try {
                                                MethodInfo addHandler = b.Target.Event.GetAddMethod ();
                                                Delegate del = Delegate.CreateDelegate (b.Target.Event.EventHandlerType, b.Source.Instance, b.Source.Method);
-                                               addHandler.Invoke (b.Target.Instance, new object[] { del });
+                                               addHandler.Invoke (b.Target.Instance, new object [] { del });
 
 #if DEBUG_BINDING
                                                Debug.WriteLine ("\tHandler binded => " + b.ToString());
 #endif
                                                b.Resolved = true;
                                        } catch (Exception ex) {
-                                               Debug.WriteLine ("\tERROR: " + ex.ToString());
+                                               Debug.WriteLine ("\tERROR: " + ex.ToString ());
                                        }
                                        continue;
                                }
@@ -274,91 +65,91 @@ namespace Crow
                                b.Resolved = true;
                        }
 
-                       MethodInfo stringEquals = typeof(string).GetMethod
-                               ("Equals", new Type[3] {typeof(string), typeof(string), typeof(StringComparison)});
-                       Type target_Type = Bindings[0].Target.Instance.GetType();
-                       EventInfo ei = typeof(IValueChange).GetEvent("ValueChanged");
+                       MethodInfo stringEquals = typeof (string).GetMethod
+                               ("Equals", new Type [3] { typeof (string), typeof (string), typeof (StringComparison) });
+                       Type target_Type = Bindings [0].Target.Instance.GetType ();
+                       EventInfo ei = typeof (IValueChange).GetEvent ("ValueChanged");
                        MethodInfo evtInvoke = ei.EventHandlerType.GetMethod ("Invoke");
-                       ParameterInfo[] evtParams = evtInvoke.GetParameters ();
+                       ParameterInfo [] evtParams = evtInvoke.GetParameters ();
                        Type handlerArgsType = evtParams [1].ParameterType;
-                       Type[] args = {typeof(object), typeof(object),handlerArgsType};
-                       FieldInfo fiNewValue = typeof(ValueChangeEventArgs).GetField("NewValue");
-                       FieldInfo fiMbName = typeof(ValueChangeEventArgs).GetField("MemberName");
+                       Type [] args = { typeof (object), typeof (object), handlerArgsType };
+                       FieldInfo fiNewValue = typeof (ValueChangeEventArgs).GetField ("NewValue");
+                       FieldInfo fiMbName = typeof (ValueChangeEventArgs).GetField ("MemberName");
 
                        //group;only one dynMethods by target (valuechanged event source)
                        //changed value name tested in switch
                        //IEnumerable<Binding[]> groupedByTarget = resolved.GroupBy (g => g.Target.Instance, g => g, (k, g) => g.ToArray ());
                        foreach (List<Binding> grouped in resolved.Values) {
                                int i = 0;
-                               Type source_Type = grouped[0].Source.Instance.GetType();
+                               Type source_Type = grouped [0].Source.Instance.GetType ();
 
                                DynamicMethod dm = null;
                                ILGenerator il = null;
 
-                               System.Reflection.Emit.Label[] jumpTable = null;
-                               System.Reflection.Emit.Label endMethod = new System.Reflection.Emit.Label();
+                               System.Reflection.Emit.Label [] jumpTable = null;
+                               System.Reflection.Emit.Label endMethod = new System.Reflection.Emit.Label ();
 
-#region Retrieve EventHandler parameter type
+                               #region Retrieve EventHandler parameter type
                                //EventInfo ei = targetType.GetEvent ("ValueChanged");
                                //no dynamic update if ValueChanged interface is not implemented
-                               if (source_Type.GetInterfaces().Contains(typeof(IValueChange))){
-                                       dm = new DynamicMethod(grouped[0].NewDynMethodId,
+                               if (source_Type.GetInterfaces ().Contains (typeof (IValueChange))) {
+                                       dm = new DynamicMethod (grouped [0].CreateNewDynMethodId (),
                                                MethodAttributes.Family | MethodAttributes.FamANDAssem | MethodAttributes.NewSlot,
                                                CallingConventions.Standard,
-                                               typeof(void),
+                                               typeof (void),
                                                args,
-                                               target_Type,true);
+                                               target_Type, true);
 
-                                       il = dm.GetILGenerator(256);
+                                       il = dm.GetILGenerator (256);
 
-                                       endMethod = il.DefineLabel();
-                                       jumpTable = new System.Reflection.Emit.Label[grouped.Count];
+                                       endMethod = il.DefineLabel ();
+                                       jumpTable = new System.Reflection.Emit.Label [grouped.Count];
                                        for (i = 0; i < grouped.Count; i++)
                                                jumpTable [i] = il.DefineLabel ();
-                                       il.DeclareLocal(typeof(string));
-                                       il.DeclareLocal(typeof(object));
+                                       il.DeclareLocal (typeof (string));
+                                       il.DeclareLocal (typeof (object));
 
-                                       il.Emit(OpCodes.Nop);
-                                       il.Emit(OpCodes.Ldarg_0);
+                                       il.Emit (OpCodes.Nop);
+                                       il.Emit (OpCodes.Ldarg_0);
                                        //il.Emit(OpCodes.Isinst, sourceType);
                                        //push new value onto stack
-                                       il.Emit(OpCodes.Ldarg_2);
-                                       il.Emit(OpCodes.Ldfld, fiNewValue);
-                                       il.Emit(OpCodes.Stloc_1);
+                                       il.Emit (OpCodes.Ldarg_2);
+                                       il.Emit (OpCodes.Ldfld, fiNewValue);
+                                       il.Emit (OpCodes.Stloc_1);
                                        //push name
-                                       il.Emit(OpCodes.Ldarg_2);
-                                       il.Emit(OpCodes.Ldfld, fiMbName);
-                                       il.Emit(OpCodes.Stloc_0);
-                                       il.Emit(OpCodes.Ldloc_0);
-                                       il.Emit(OpCodes.Brfalse, endMethod);
+                                       il.Emit (OpCodes.Ldarg_2);
+                                       il.Emit (OpCodes.Ldfld, fiMbName);
+                                       il.Emit (OpCodes.Stloc_0);
+                                       il.Emit (OpCodes.Ldloc_0);
+                                       il.Emit (OpCodes.Brfalse, endMethod);
                                }
-#endregion
+                               #endregion
 
                                i = 0;
                                foreach (Binding b in grouped) {
-#region initialize target with actual value
+                                       #region initialize target with actual value
                                        object targetValue = null;
-                                       if (b.Source.Member != null){
+                                       if (b.Source.Member != null) {
                                                if (b.Source.Member.MemberType == MemberTypes.Property)
                                                        targetValue = b.Source.Property.GetGetMethod ().Invoke (b.Source.Instance, null);
                                                else if (b.Source.Member.MemberType == MemberTypes.Field)
                                                        targetValue = b.Source.Field.GetValue (b.Source.Instance);
-                                               else if (b.Source.Member.MemberType == MemberTypes.Method){
+                                               else if (b.Source.Member.MemberType == MemberTypes.Method) {
                                                        MethodInfo mthSrc = b.Source.Method;
-                                                       if (mthSrc.IsDefined(typeof(ExtensionAttribute), false))
-                                                               targetValue = mthSrc.Invoke(null, new object[] {b.Source.Instance});
+                                                       if (mthSrc.IsDefined (typeof (ExtensionAttribute), false))
+                                                               targetValue = mthSrc.Invoke (null, new object [] { b.Source.Instance });
                                                        else
-                                                               targetValue = mthSrc.Invoke(b.Source.Instance, null);
-                                               }else
+                                                               targetValue = mthSrc.Invoke (b.Source.Instance, null);
+                                               } else
                                                        throw new Exception ("unandled source member type for binding");
-                                       }else if (string.IsNullOrEmpty(b.Expression))
-                                               targetValue= grouped [0].Source.Instance;//empty binding exp=> bound to target object by default
-                                       //TODO: handle other dest type conversions
-                                       if (b.Target.Property.PropertyType == typeof(string)){
-                                               if (targetValue == null){
+                                       } else if (string.IsNullOrEmpty (b.Expression))
+                                               targetValue = grouped [0].Source.Instance;//empty binding exp=> bound to target object by default
+                                                                                                                                 //TODO: handle other dest type conversions
+                                       if (b.Target.Property.PropertyType == typeof (string)) {
+                                               if (targetValue == null) {
                                                        //set default value
 
-                                               }else
+                                               } else
                                                        targetValue = targetValue.ToString ();
                                        }
                                        try {
@@ -371,7 +162,7 @@ namespace Crow
                                        } catch (Exception ex) {
                                                Debug.WriteLine (ex.ToString ());
                                        }
-#endregion
+                                       #endregion
 
                                        //if no dyn update, skip jump table
                                        if (il == null)
@@ -381,10 +172,10 @@ namespace Crow
                                        if (b.Source.Member != null)
                                                il.Emit (OpCodes.Ldstr, b.Source.Member.Name);
                                        else
-                                               il.Emit (OpCodes.Ldstr, b.Expression.Split('/').LastOrDefault());
+                                               il.Emit (OpCodes.Ldstr, b.Expression.Split ('/').LastOrDefault ());
                                        il.Emit (OpCodes.Ldc_I4_4);//StringComparison.Ordinal
                                        il.Emit (OpCodes.Callvirt, stringEquals);
-                                       il.Emit (OpCodes.Brtrue, jumpTable[i]);
+                                       il.Emit (OpCodes.Brtrue, jumpTable [i]);
                                        i++;
                                }
 
@@ -394,8 +185,8 @@ namespace Crow
                                il.Emit (OpCodes.Br, endMethod);
 
                                i = 0;
-                               foreach (Binding b in grouped) {                                        
-                                       
+                               foreach (Binding b in grouped) {
+
                                        il.MarkLabel (jumpTable [i]);
 
 
@@ -428,19 +219,19 @@ namespace Crow
 
 
 
-                                       if (b.Target.Property.PropertyType == typeof(string)) {
+                                       if (b.Target.Property.PropertyType == typeof (string)) {
                                                MemberReference tostring = new MemberReference (b.Target.Instance);
-                                               if (!tostring.FindMember ("ToString"))
+                                               if (!tostring.TryFindMember ("ToString"))
                                                        throw new Exception ("ToString method not found");
                                                il.Emit (OpCodes.Callvirt, tostring.Method);
                                        } else if (!sourceValueType.IsValueType)
                                                il.Emit (OpCodes.Castclass, sourceValueType);
                                        else if (b.Target.Property.PropertyType != sourceValueType) {
                                                il.Emit (OpCodes.Callvirt, CompilerServices.GetConvertMethod (b.Target.Property.PropertyType));
-                                       }else
-                                               il.Emit(OpCodes.Unbox_Any, b.Target.Property.PropertyType);
+                                       } else
+                                               il.Emit (OpCodes.Unbox_Any, b.Target.Property.PropertyType);
 
-                                       il.Emit(OpCodes.Callvirt, b.Target.Property.GetSetMethod());
+                                       il.Emit (OpCodes.Callvirt, b.Target.Property.GetSetMethod ());
 
                                        //il.BeginCatchBlock (typeof (Exception));
                                        //il.Emit (OpCodes.Pop);
@@ -450,176 +241,179 @@ namespace Crow
                                        i++;
 
                                }
-                               il.MarkLabel(endMethod);
-                               il.Emit(OpCodes.Pop);
-                               il.Emit(OpCodes.Ret);
+                               il.MarkLabel (endMethod);
+                               il.Emit (OpCodes.Pop);
+                               il.Emit (OpCodes.Ret);
 
-                               Delegate del = dm.CreateDelegate(ei.EventHandlerType, Bindings[0].Target.Instance);
+                               Delegate del = dm.CreateDelegate (ei.EventHandlerType, Bindings [0].Target.Instance);
                                MethodInfo addHandler = ei.GetAddMethod ();
-                               addHandler.Invoke(grouped [0].Source.Instance, new object[] {del});
+                               addHandler.Invoke (grouped [0].Source.Instance, new object [] { del });
                        }
                }
 
                /// <summary>
                /// Compile events expression in GOML attributes
                /// </summary>
-               /// <param name="es">Event binding details</param>
-               public static void CompileEventSource(Binding binding)
+               /// <param name="binding">Event binding details</param>
+               public static void CompileEventSource (Binding binding)
                {
 #if DEBUG_BINDING
                        Debug.WriteLine ("\tCompile Event Source => " + binding.ToString());
 #endif
 
-                       Type target_type = binding.Target.Instance.GetType();
+                       Type target_type = binding.Target.Instance.GetType ();
 
-#region Retrieve EventHandler parameter type
+                       #region Retrieve EventHandler parameter type
                        MethodInfo evtInvoke = binding.Target.Event.EventHandlerType.GetMethod ("Invoke");
-                       ParameterInfo[] evtParams = evtInvoke.GetParameters ();
+                       ParameterInfo [] evtParams = evtInvoke.GetParameters ();
                        Type handlerArgsType = evtParams [1].ParameterType;
-#endregion
+                       #endregion
 
-                       Type[] args = {typeof(object), typeof(object),handlerArgsType};
-                       DynamicMethod dm = new DynamicMethod(binding.NewDynMethodId,
-                               typeof(void),
+                       Type [] args = { typeof (object), typeof (object), handlerArgsType };
+                       DynamicMethod dm = new DynamicMethod (binding.CreateNewDynMethodId (),
+                               typeof (void),
                                args,
                                target_type);
 
 
-#region IL generation
-                       ILGenerator il = dm.GetILGenerator(256);
+                       #region IL generation
+                       ILGenerator il = dm.GetILGenerator (256);
 
-                       string src = binding.Expression.Trim();
+                       string src = binding.Expression.Trim ();
 
-                       if (! (src.StartsWith("{") || src.EndsWith ("}")))
-                               throw new Exception (string.Format("GOML:Malformed {0} Event handler: {1}", binding.Target.Member.Name, binding.Expression));
+                       if (!(src.StartsWith ("{") || src.EndsWith ("}")))
+                               throw new Exception (string.Format ("GOML:Malformed {0} Event handler: {1}", binding.Target.Member.Name, binding.Expression));
 
                        src = src.Substring (1, src.Length - 2);
-                       string[] srcLines = src.Split (new char[] { ';' });
+                       string [] srcLines = src.Split (new char [] { ';' });
 
                        foreach (string srcLine in srcLines) {
                                string statement = srcLine.Trim ();
 
-                               string[] operandes = statement.Split (new char[] { '=' });
+                               string [] operandes = statement.Split (new char [] { '=' });
                                if (operandes.Length < 2) //not an affectation
                                {
                                        continue;
                                }
                                string lop = operandes [0].Trim ();
-                               string rop = operandes [operandes.Length-1].Trim ();
+                               string rop = operandes [operandes.Length - 1].Trim ();
 
-#region LEFT OPERANDES
-                               GraphicObject lopObj = binding.Target.Instance as GraphicObject;        //default left operand base object is
-                               //the first arg (object sender) of the event handler
+                               #region LEFT OPERANDES
+                               GraphicObject lopObj = binding.Target.Instance as GraphicObject;    //default left operand base object is
+                                                                                                                                                                       //the first arg (object sender) of the event handler
 
-                               il.Emit(OpCodes.Ldarg_0);       //load sender ref onto the stack
+                               il.Emit (OpCodes.Ldarg_0);  //load sender ref onto the stack
 
-                               string[] lopParts = lop.Split (new char[] { '.' });
+                               string [] lopParts = lop.Split (new char [] { '.' });
                                if (lopParts.Length > 1) {//should search also for member of es.Source
-                                       MethodInfo FindByNameMi = typeof(GraphicObject).GetMethod("FindByName");
+                                       MethodInfo FindByNameMi = typeof (GraphicObject).GetMethod ("FindByName");
                                        for (int j = 0; j < lopParts.Length - 1; j++) {
-                                               il.Emit (OpCodes.Ldstr, lopParts[j]);
-                                               il.Emit(OpCodes.Callvirt, FindByNameMi);
+                                               il.Emit (OpCodes.Ldstr, lopParts [j]);
+                                               il.Emit (OpCodes.Callvirt, FindByNameMi);
                                        }
                                }
 
-                               int i = lopParts.Length -1;
+                               int i = lopParts.Length - 1;
 
-                               MemberInfo[] lopMbis = lopObj.GetType().GetMember (lopParts[i]);
+                               MemberInfo [] lopMbis = lopObj.GetType ().GetMember (lopParts [i]);
 
-                               if (lopMbis.Length<1)
-                                       throw new Exception (string.Format("CROW BINDING: Member not found '{0}'", lop));
+                               if (lopMbis.Length < 1)
+                                       throw new Exception (string.Format ("CROW BINDING: Member not found '{0}'", lop));
 
                                OpCode lopSetOC;
                                dynamic lopSetMbi;
                                Type lopT = null;
-                               switch (lopMbis[0].MemberType) {
+                               switch (lopMbis [0].MemberType) {
                                case MemberTypes.Property:
-                                       PropertyInfo lopPi = target_type.GetProperty (lopParts[i]);
+                                       PropertyInfo lopPi = target_type.GetProperty (lopParts [i]);
                                        MethodInfo dstMi = lopPi.GetSetMethod ();
                                        lopT = lopPi.PropertyType;
                                        lopSetMbi = dstMi;
                                        lopSetOC = OpCodes.Callvirt;
                                        break;
                                case MemberTypes.Field:
-                                       FieldInfo dstFi = target_type.GetField(lopParts[i]);
+                                       FieldInfo dstFi = target_type.GetField (lopParts [i]);
                                        lopT = dstFi.FieldType;
                                        lopSetMbi = dstFi;
                                        lopSetOC = OpCodes.Stfld;
                                        break;
                                default:
-                                       throw new Exception (string.Format("GOML:member type not handle: {0}", lopParts[i]));
+                                       throw new Exception (string.Format ("GOML:member type not handle: {0}", lopParts [i]));
                                }
-#endregion
+                               #endregion
 
-#region RIGHT OPERANDES
-                               if (rop.StartsWith("\'")){
-                                       if (!rop.EndsWith("\'"))
+                               #region RIGHT OPERANDES
+                               if (rop.StartsWith ("\'")) {
+                                       if (!rop.EndsWith ("\'"))
                                                throw new Exception (string.Format
                                                        ("GOML:malformed string constant in handler: {0}", rop));
                                        string strcst = rop.Substring (1, rop.Length - 2);
 
-                                       il.Emit(OpCodes.Ldstr,strcst);
+                                       il.Emit (OpCodes.Ldstr, strcst);
 
-                               }else{
+                               } else {
                                        if (lopT.IsEnum)
-                                               throw new NotImplementedException();
+                                               throw new NotImplementedException ();
 
-                                       MethodInfo lopParseMi = lopT.GetMethod("Parse");
+                                       MethodInfo lopParseMi = lopT.GetMethod ("Parse");
                                        if (lopParseMi == null)
                                                throw new Exception (string.Format
                                                        ("GOML:no parse method found in: {0}", lopT.Name));
-                                       il.Emit(OpCodes.Ldstr, rop);
-                                       il.Emit(OpCodes.Callvirt, lopParseMi);
-                                       il.Emit(OpCodes.Unbox_Any, lopT);
+                                       il.Emit (OpCodes.Ldstr, rop);
+                                       il.Emit (OpCodes.Callvirt, lopParseMi);
+                                       il.Emit (OpCodes.Unbox_Any, lopT);
                                }
 
-#endregion
+                               #endregion
 
                                //emit left operand assignment
-                               il.Emit(lopSetOC, lopSetMbi);
+                               il.Emit (lopSetOC, lopSetMbi);
                        }
 
-                       il.Emit(OpCodes.Ret);
+                       il.Emit (OpCodes.Ret);
 
-#endregion
+                       #endregion
 
-                       Delegate del = dm.CreateDelegate(binding.Target.Event.EventHandlerType, binding.Target.Instance);
+                       Delegate del = dm.CreateDelegate (binding.Target.Event.EventHandlerType, binding.Target.Instance);
                        MethodInfo addHandler = binding.Target.Event.GetAddMethod ();
-                       addHandler.Invoke(binding.Target.Instance, new object[] {del});
+                       addHandler.Invoke (binding.Target.Instance, new object [] { del });
 
                        binding.Resolved = true;
                }
 
-#region conversions
+               #region conversions
 
-               internal static MethodInfo GetConvertMethod( Type targetType )
+               internal static MethodInfo GetConvertMethod (Type targetType)
                {
                        string name;
 
-                       if( targetType == typeof( bool ) )
+                       if (targetType == typeof (bool))
                                name = "ToBoolean";
-                       else if( targetType == typeof( byte ) )
+                       else if (targetType == typeof (byte))
                                name = "ToByte";
-                       else if( targetType == typeof( short ) )
+                       else if (targetType == typeof (short))
                                name = "ToInt16";
-                       else if( targetType == typeof( int ) )
+                       else if (targetType == typeof (int))
                                name = "ToInt32";
-                       else if( targetType == typeof( long ) )
+                       else if (targetType == typeof (long))
                                name = "ToInt64";
-                       else if( targetType == typeof( double ) )
+                       else if (targetType == typeof (double))
                                name = "ToDouble";
-                       else if( targetType == typeof( float ) )
+                       else if (targetType == typeof (float))
                                name = "ToSingle";
-                       else if (targetType == typeof (string ) )
-                               return typeof(object).GetMethod("ToString", Type.EmptyTypes);
+                       else if (targetType == typeof (string))
+                               return typeof (object).GetMethod ("ToString", Type.EmptyTypes);
                        else //try to find implicit convertion
-                               throw new NotImplementedException( string.Format( "Conversion to {0} is not implemented.", targetType.Name ) );
+                               throw new NotImplementedException (string.Format ("Conversion to {0} is not implemented.", targetType.Name));
 
-                       return typeof( Convert ).GetMethod( name, BindingFlags.Static | BindingFlags.Public, null, new Type[] { typeof( object ) }, null );
+                       return typeof (Convert).GetMethod (name, BindingFlags.Static | BindingFlags.Public, null, new Type [] { typeof (object) }, null);
                }
-#endregion
-                       
-               public static FieldInfo GetEventHandlerField(Type type, string eventName)
+               #endregion
+
+               /// <summary>
+               /// retrieve event handler in class or ancestors
+               /// </summary>
+               public static FieldInfo GetEventHandlerField (Type type, string eventName)
                {
                        FieldInfo fi;
                        Type ty = type;
@@ -631,17 +425,17 @@ namespace Crow
                                ty = ty.BaseType;
                                if (ty == null)
                                        break;
-                       } while(fi == null);
+                       } while (fi == null);
                        return fi;
                }
-       
+
                /// <summary>
                /// Gets extension methods defined in assembley for extendedType
                /// </summary>
                /// <returns>Extension methods enumerable</returns>
                /// <param name="assembly">Assembly</param>
                /// <param name="extendedType">Extended type to search for</param>
-               public static IEnumerable<MethodInfo> GetExtensionMethods(Assembly assembly,
+               public static IEnumerable<MethodInfo> GetExtensionMethods (Assembly assembly,
                        Type extendedType)
                {
                        IEnumerable<MethodInfo> query = null;
@@ -649,19 +443,19 @@ namespace Crow
 
                        do {
                                query = from type in assembly.GetTypes ()
-                                       where type.IsSealed && !type.IsGenericType && !type.IsNested
-                                       from method in type.GetMethods (BindingFlags.Static
-                                           | BindingFlags.Public | BindingFlags.NonPublic)
-                                       where method.IsDefined (typeof(ExtensionAttribute), false)
-                                       where method.GetParameters () [0].ParameterType == curType
-                                       select method;
-
-                               if (query.Count() > 0)
+                                               where type.IsSealed && !type.IsGenericType && !type.IsNested
+                                               from method in type.GetMethods (BindingFlags.Static
+                                                       | BindingFlags.Public | BindingFlags.NonPublic)
+                                               where method.IsDefined (typeof (ExtensionAttribute), false)
+                                               where method.GetParameters () [0].ParameterType == curType
+                                               select method;
+
+                               if (query.Count () > 0)
                                        break;
-                               
+
                                curType = curType.BaseType;
                        } while (curType != null);
-                               
+
                        return query;
                }
        }
diff --git a/src/CompilerServices/MemberReference.cs b/src/CompilerServices/MemberReference.cs
new file mode 100644 (file)
index 0000000..1dc3a3e
--- /dev/null
@@ -0,0 +1,73 @@
+//
+//  MemberReference.cs
+//
+//  Author:
+//       Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+//  Copyright (c) 2016 jp
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+using System;
+using System.Linq;
+using System.Reflection;
+
+namespace Crow
+{
+       /// <summary>
+       /// link MemberInfo and instance in one class
+       /// </summary>
+       public class MemberReference
+       {               
+               public object Instance;
+               public MemberInfo Member;
+
+               public PropertyInfo Property { get { return Member as PropertyInfo; } }
+               public FieldInfo Field { get { return Member as FieldInfo; } }
+               public EventInfo Event { get { return Member as EventInfo; } }
+               public MethodInfo Method { get { return Member as MethodInfo; } }
+
+               #region CTOR
+               public MemberReference () {}
+               public MemberReference (object _instance, MemberInfo _member = null)
+               {
+                       Instance = _instance;
+                       Member = _member;
+               }
+               #endregion
+
+               /// <summary>
+               /// Try to find member by name in instance class or, if not found,
+               /// in extension methods
+               /// </summary>
+               /// <returns>True if found, false otherwise</returns>
+               /// <param name="_memberName">Member name to search for</param>
+               public bool TryFindMember (string _memberName)
+               {
+                       if (Instance == null)
+                               return false;
+                       Type t = Instance.GetType ();
+                       Member = t.GetMember (_memberName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance).FirstOrDefault ();
+
+                       #region search for extensions methods if member not found in type
+                       if (Member == null && !string.IsNullOrEmpty (_memberName)) {
+                               Assembly a = Assembly.GetExecutingAssembly ();
+                               Member = CompilerServices.GetExtensionMethods (a, t).Where (em => em.Name == _memberName).FirstOrDefault ();
+                       }
+                       #endregion
+
+                       return Member != null;
+               }
+       }
+}
+
index 6175b2d83ec704d2bdc4de3c49574499191e8685..75fe4b6316db2ced33e9eb4ba8dcad92844f7e5c 100644 (file)
@@ -22,10 +22,8 @@ namespace Crow
 
                #endregion
 
-               #if DEBUG_LAYOUTING
                internal static ulong currentUid = 0;
                internal ulong uid = 0;
-               #endif
 
 
                internal int layoutingTries = 0;
@@ -44,10 +42,8 @@ namespace Crow
                #region CTOR
                public GraphicObject ()
                {
-                       #if DEBUG_LAYOUTING
                        uid = currentUid;
                        currentUid++;
-                       #endif
 
                        if (Interface.XmlSerializerInit)
                                return;
index 642c1e9ef277d781de1a44390b7452f97a643125..45ff58648cb53009913cc6579a3b22c9a1f24d15 100644 (file)
@@ -26,6 +26,7 @@ namespace Crow
        public interface IBindable
        {
                List<Binding> Bindings { get; }
+               object DataSource { get; set; }
        }
 }