]> O.S.I.I.S - jp/crow.git/commitdiff
first tests with DataSourceType to prevent using reflexion too often in bindings
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Sat, 15 Dec 2018 06:13:54 +0000 (07:13 +0100)
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Sat, 15 Dec 2018 06:13:54 +0000 (07:13 +0100)
Crow/src/CompilerServices/CompilerServices.cs
Crow/src/IML/IMLContext.cs
Crow/src/IML/Node.cs
Crow/src/Instantiator.cs
Tests/BasicTests.cs
Tests/Interfaces/GraphicObject/0.crow

index ee6770a8001b378647db3a2398ad769bb487a3aa..80e47e9d77c8c3a4caf5479809ead156869c3ae8 100644 (file)
@@ -382,8 +382,6 @@ namespace Crow.IML
                                                tmp = gi.Invoke(instance, null);
                                        dstType = gi.ReturnType;
                                }
-
-
                                if (tmp != null)
                                        return tmp;
                                if (dstType == typeof(string) || dstType == typeof (object))//TODO:object should be allowed to return null and not ""
@@ -397,23 +395,6 @@ namespace Crow.IML
 
                        return null;
                }
-               
-               /// <summary>
-               /// search for extentions method in entry assembly then in assembly where the type is defined
-               /// </summary>
-               /// <returns>Extention MethodInfo</returns>
-               /// <param name="t">Extended type</param>
-               /// <param name="methodName">Extention method name</param>
-               //internal static MethodInfo SearchExtMethod(Type t, string methodName){
-               //      MethodInfo mi = null;
-               //      mi = GetExtensionMethods (Assembly.GetEntryAssembly(), t)
-               //              .Where (em => em.Name == methodName).FirstOrDefault ();
-               //      if (mi != null)
-               //              return mi;
-
-               //      return GetExtensionMethods (t.Module.Assembly, t)
-               //              .Where (em => em.Name == methodName).FirstOrDefault ();
-               //}
                internal static MethodInfo SearchExtMethod (Type t, string methodName)
                {
                        string key = t.Name + "." + methodName;
@@ -997,6 +978,77 @@ namespace Crow.IML
 
                        return fi.GetValue (data);
                }
+               internal static MemberInfo GetMemberInfo (Type dataType, string member, out Type returnType)
+               {
+                       MethodInfo miGetDatas = dataType.GetMethod (member, new Type [] { });
+                       if (miGetDatas != null) {
+                               returnType = miGetDatas.ReturnType;
+                               return miGetDatas;
+                       }
+
+                       MemberInfo mbi = dataType.GetMember (member).FirstOrDefault ();
+                       if (mbi == null)
+                               miGetDatas = CompilerServices.SearchExtMethod (dataType, member);
+                       else {
+                               if (mbi is FieldInfo) {
+                                       FieldInfo fi = mbi as FieldInfo;
+                                       returnType = fi.FieldType;
+                                       return mbi;
+                               }
+                               if (mbi.MemberType == MemberTypes.Property)
+                                       miGetDatas = (mbi as PropertyInfo).GetGetMethod ();
+                               else
+                                       miGetDatas = mbi as MethodInfo;
+                       }
+                       returnType = miGetDatas?.ReturnType;
+                       return miGetDatas;
+
+               }
+               internal static void emitGetMemberValue (ILGenerator il, Type dataType, MemberInfo mi)
+               {
+                       switch (mi.MemberType) {
+                       case MemberTypes.Method:
+                               MethodInfo mim = mi as MethodInfo;
+                               if (mim.IsStatic)
+                                       il.Emit (OpCodes.Call, mim);
+                               else
+                                       il.Emit (OpCodes.Callvirt, mim);
+                               break;
+                       case MemberTypes.Field:
+                               il.Emit (OpCodes.Ldfld, mi as FieldInfo);
+                               break;
+                       }
+               }
+               //object is already on the stack
+               internal static void emitGetMemberValue (ILGenerator il, Type dataType, string member)
+               {
+                       MethodInfo miGetDatas = dataType.GetMethod (member, new Type [] { });
+                       if (miGetDatas != null) {
+                               il.Emit (OpCodes.Callvirt, miGetDatas);
+                               return;
+                       }
+                       MemberInfo mbi = dataType.GetMember (member).FirstOrDefault ();
+                       if (mbi == null) {
+                               MethodInfo miExt = CompilerServices.SearchExtMethod (dataType, member);
+                               if (miExt == null)//and among fields
+                                       throw new Exception ($"member {member} not found in {dataType}");
+                               il.Emit (OpCodes.Call, miExt);
+                               return;
+                       }
+                       if (mbi.MemberType == MemberTypes.Property) {
+                               miGetDatas = (mbi as PropertyInfo)?.GetGetMethod ();
+                               if (miGetDatas == null)
+                                       throw new Exception ($"no getter found for property {member} in {dataType}");
+                               il.Emit (OpCodes.Callvirt, miGetDatas);
+                               return;
+                       }
+
+                       FieldInfo fi = mbi as FieldInfo;
+                       if (fi == null)
+                               throw new Exception ($"member {member} not found in {dataType}");
+
+                       il.Emit (OpCodes.Ldfld, fi);
+               }
        }
 }
 
index 8e12c41bfbdb45619c11c91b3e7a214ea9d152eb..a0e95bef11cf6cdb43c68daa35b73eb86f830027 100644 (file)
@@ -80,6 +80,39 @@ namespace Crow.IML
                        CompilerServices.emitSetCurInterface (il);
                }
 
+               Type curDataSourceType = null;
+               /// <summary>
+               /// Pushs  new node and set datasourcetype to current ds type
+               /// </summary>
+               /// <param name="crowType">Crow type.</param>
+               /// <param name="_index">Index.</param>
+               public void PushNode (Type crowType, int _index = 0) {
+                       nodesStack.Push (new Node (crowType, _index, curDataSourceType));
+               }
+               /// <summary>
+               /// Pops node and set curDS type to previous one in node on top of the stack
+               /// </summary>
+               /// <returns>The node.</returns>
+               public Node PopNode () {
+                       Node n = nodesStack.Pop ();
+                       if (nodesStack.Count > 0)
+                               curDataSourceType = nodesStack.Peek().DataSourceType;
+                       return n;
+               }
+               public bool CurrentNodeHasDataSourceType {
+                       get { return curDataSourceType != null; }
+               }
+               public Type CurrentDataSourceType {
+                       get { return curDataSourceType; }
+               }
+               public void SetDataSourceTypeForCurrentNode (Type dsType)
+               {
+                       Node n = nodesStack.Pop ();
+                       n.DataSourceType = dsType;
+                       nodesStack.Push (n);
+                       curDataSourceType = dsType;
+               }
+
                public NodeAddress CurrentNodeAddress {
                        get {
                                Node[] n = nodesStack.ToArray ();
@@ -185,7 +218,6 @@ namespace Crow.IML
                /// Emits the handler method addition, done at end of parsing, Loc_0 is root node instance
                /// </summary>
                /// <param name="bd">Bd.</param>
-               /// <param name="evt">passed as arg to prevent refetching it for the 3rd time</param>
                public void emitHandlerMethodAddition(EventBinding bd){
 
                        //fetch source instance with address for handler addition (as 1st arg of handler.add)
index 2ca90e8c098b515ddb32d59360b92ac1d0e26c4b..5ba93968f826c9e392872d309d10fe76208c3405 100644 (file)
@@ -37,17 +37,23 @@ namespace Crow.IML
        public struct Node
        {
                #region CTOR
-               public Node (Type crowType, int _index = 0)
+               public Node (Type crowType, int _index = 0, Type dsType = null)
                {
                        CrowType = crowType;
                        Index = _index;
+                       DataSourceType = dsType;
                }
                #endregion
 
                /// <summary> Current node type</summary>
-               public Type CrowType;
+               public readonly Type CrowType;
                /// <summary> Index in parent, -1 for template</summary>
-               public int Index;
+               public readonly int Index;
+               /// <summary>
+               /// DataSourceType attribute if set
+               /// </summary>
+               public Type DataSourceType;
+
 
                /// <summary>
                /// retrieve the child addition method depending on the type of this node
@@ -68,7 +74,7 @@ namespace Crow.IML
                        return null;
                }
 
-               #region Equality Compare
+#region Equality Compare
                public override bool Equals (object obj)
                {
                        if (obj == null) 
@@ -80,7 +86,7 @@ namespace Crow.IML
                {
                        return CrowType.GetHashCode () ^ Index.GetHashCode ();
                }
-               #endregion
+#endregion
 
                public bool HasTemplate {
                        get { return typeof (TemplatedControl).IsAssignableFrom (CrowType);}
@@ -88,6 +94,9 @@ namespace Crow.IML
                public bool IsTemplatedGroup {
                        get { return typeof (TemplatedGroup).IsAssignableFrom (CrowType);}
                }
+               public bool HasDataSourceType {
+                       get { return DataSourceType != null; }
+               }
 
                public static implicit operator string (Node sn)
                {
index 14218bfc6f85cee1cadfc60219e49ff07af93055..8c5a4d466e5d893d988e4a893144b85430773c48 100644 (file)
@@ -206,9 +206,9 @@ namespace Crow.IML
                void parseIML (XmlReader reader) {
                        IMLContext ctx = new IMLContext (findRootType (reader));
 
-                       ctx.nodesStack.Push (new Node (ctx.RootType));
+                       ctx.PushNode (ctx.RootType);
                        emitLoader (reader, ctx);
-                       ctx.nodesStack.Pop ();
+                       ctx.PopNode ();
 
                        foreach (int idx in templateCachedDelegateIndices)
                                ctx.emitCachedDelegateHandlerAddition(idx, CompilerServices.eiLogicalParentChanged);
@@ -429,7 +429,7 @@ namespace Crow.IML
                        using (XmlTextReader reader = new XmlTextReader (tmpXml, XmlNodeType.Element, null)) {
                                reader.Read ();
 
-                               #if DESIGN_MODE
+#if DESIGN_MODE
                                IXmlLineInfo li = (IXmlLineInfo)reader;
                                ctx.il.Emit (OpCodes.Ldloc_0);
                                ctx.il.Emit (OpCodes.Ldstr, this.NextDesignID);
@@ -450,23 +450,33 @@ namespace Crow.IML
                                //first check for Style attribute then trigger default value loading
                                if (reader.HasAttributes) {
                                        string style = reader.GetAttribute ("Style");
-                                       if (!string.IsNullOrEmpty (style)){
+                                       if (!string.IsNullOrEmpty (style)) {
                                                CompilerServices.EmitSetValue (ctx.il, CompilerServices.piStyle, style);
-                                               #if DESIGN_MODE
+#if DESIGN_MODE
                                                emitSetDesignAttribute (ctx, "Style", style);
-                                               #endif
+#endif
                                        }
+                                       //check for dataSourceType, if set, datasource bindings will use direct setter/getter
+                                       //instead of reflexion
+                                       string dataSourceType = reader.GetAttribute ("DataSourceType");
+                                       if (string.IsNullOrEmpty (dataSourceType)) {
+                                               //if not set but dataSource is not null, reset dsType to null
+                                               string ds = reader.GetAttribute ("DataSource");
+                                               if (!string.IsNullOrEmpty (ds)) 
+                                                       ctx.SetDataSourceTypeForCurrentNode (null);
+                                       } else
+                                               ctx.SetDataSourceTypeForCurrentNode(CompilerServices.getTypeFromName (dataSourceType));
                                }
-                ctx.il.Emit (OpCodes.Ldloc_0);
+                               ctx.il.Emit (OpCodes.Ldloc_0);
                 ctx.il.Emit (OpCodes.Callvirt, CompilerServices.miLoadDefaultVals);
-                #endregion
+#endregion
 
 
                                #region Attributes reading
                                if (reader.HasAttributes) {
 
                                        while (reader.MoveToNextAttribute ()) {
-                                               if (reader.Name == "Style")
+                                               if (reader.Name == "Style" || reader.Name == "DataSourceType")
                                                        continue;
 
                                                #if DESIGN_MODE
@@ -575,13 +585,16 @@ namespace Crow.IML
                        NodeAddress sourceNA = ctx.CurrentNodeAddress;
                        BindingDefinition bindingDef = sourceNA.GetBindingDef (sourceMember, expression);
 
-                       #if DEBUG_BINDING
+#if DEBUG_BINDING
                        Debug.WriteLine("Property Binding: " + bindingDef.ToString());
-                       #endif
+#endif
 
-                       if (bindingDef.IsDataSourceBinding)//bind on data source
-                               emitDataSourceBindings (ctx, bindingDef);
-                       else
+                       if (bindingDef.IsDataSourceBinding) {//bind on data source
+                               if (ctx.CurrentNodeHasDataSourceType)
+                                       emitDataSourceBindings (ctx, bindingDef, ctx.CurrentDataSourceType);
+                               else
+                                       emitDataSourceBindings (ctx, bindingDef);
+                       } else
                                ctx.StorePropertyBinding (bindingDef);
                }
 
@@ -591,7 +604,7 @@ namespace Crow.IML
                                (dataSource as IValueChange).ValueChanged +=
                                        (EventHandler<ValueChangeEventArgs>)dsValueChangedDynMeths [dynMethIdx].CreateDelegate (typeof(EventHandler<ValueChangeEventArgs>), dscSource);
                }
-               /// <summary> Emits remove old data source event handler./summary>
+               /// <summary> Emits remove old data source event handler.</summary>
                void emitRemoveOldDataSourceHandler(ILGenerator il, string eventName, string delegateName, bool DSSide = true){
                        System.Reflection.Emit.Label cancel = il.DefineLabel ();
 
@@ -968,6 +981,165 @@ namespace Crow.IML
                        ctx.emitCachedDelegateHandlerAddition(delDSIndex, CompilerServices.eiLogicalParentChanged);
                }
                /// <summary>
+               /// data source binding with known data type
+               /// </summary>
+               void emitDataSourceBindings (IMLContext ctx, BindingDefinition bindingDef, Type dsType)
+               {
+#if DEBUG_BINDING_FUNC_CALLS
+                       Console.WriteLine ($"emitDataSourceBindings with data type knows: {bindingDef}");
+#endif
+                       DynamicMethod dm = null;
+                       ILGenerator il = null;
+                       int dmVC = 0;
+                       PropertyInfo piSource = ctx.CurrentNodeType.GetProperty (bindingDef.SourceMember);
+                       //if no dataSource member name is provided, valuechange is not handle and datasource change
+                       //will be used as origine value
+                       string delName = "dyn_DSvalueChanged" + NewId;
+                       if (!string.IsNullOrEmpty (bindingDef.TargetMember)) {
+                               #region create valuechanged method
+                               dm = new DynamicMethod (delName,
+                                       typeof (void),
+                                       CompilerServices.argsBoundValueChange, true);
+
+                               il = dm.GetILGenerator (256);
+
+                               System.Reflection.Emit.Label endMethod = il.DefineLabel ();
+
+                               il.DeclareLocal (typeof (object));
+
+                               il.Emit (OpCodes.Nop);
+
+                               //load value changed member name onto the stack
+                               il.Emit (OpCodes.Ldarg_2);
+                               il.Emit (OpCodes.Ldfld, CompilerServices.fiVCMbName);
+
+                               //test if it's the expected one
+                               il.Emit (OpCodes.Ldstr, bindingDef.TargetMember);
+                               il.Emit (OpCodes.Ldc_I4_4);//StringComparison.Ordinal
+                               il.Emit (OpCodes.Call, CompilerServices.stringEquals);
+                               il.Emit (OpCodes.Brfalse, endMethod);
+                               //set destination member with valueChanged new value
+                               //load destination ref
+                               il.Emit (OpCodes.Ldarg_0);
+                               //load new value onto the stack
+                               il.Emit (OpCodes.Ldarg_2);
+                               il.Emit (OpCodes.Ldfld, CompilerServices.fiVCNewValue);
+
+                               //by default, source value type is deducted from target member type to allow
+                               //memberless binding, if targetMember exists, it will be used to determine target
+                               //value type for conversion
+                               CompilerServices.emitConvert (il, piSource.PropertyType);
+
+                               if (!piSource.CanWrite)
+                                       throw new Exception ("Source member of bindind is read only:" + piSource.ToString ());
+
+                               il.Emit (OpCodes.Callvirt, piSource.GetSetMethod ());
+
+                               il.MarkLabel (endMethod);
+                               il.Emit (OpCodes.Ret);
+
+                               //vc dyn meth is stored in a cached list, it will be bound to datasource only
+                               //when datasource of source graphic object changed
+                               dmVC = dsValueChangedDynMeths.Count;
+                               dsValueChangedDynMeths.Add (dm);
+                               #endregion
+                       }
+
+                       #region emit dataSourceChanged event handler
+                       //now we create the datasource changed method that will init the destination member with
+                       //the actual value of the origin member of the datasource and then will bind the value changed
+                       //dyn methode.
+                       //dm is bound to the instanciator instance to have access to cached dyn meth and delegates
+                       dm = new DynamicMethod ("dyn_dschanged" + NewId,
+                               typeof (void),
+                               CompilerServices.argsBoundDSChange, true);
+
+                       il = dm.GetILGenerator (256);
+
+                       il.DeclareLocal (typeof (object));//used for checking propery less bindings
+                       il.DeclareLocal (typeof (MemberInfo));//used for checking propery less bindings
+                       il.DeclareLocal (typeof (object));//new datasource store, save one field access
+                       System.Reflection.Emit.Label cancel = il.DefineLabel ();
+                       System.Reflection.Emit.Label newDSIsNull = il.DefineLabel ();
+                       System.Reflection.Emit.Label cancelInit = il.DefineLabel ();
+
+                       il.Emit (OpCodes.Nop);
+
+                       il.Emit (OpCodes.Ldarg_2);//load datasource change arg
+                       il.Emit (OpCodes.Ldfld, CompilerServices.fiDSCNewDS);
+                       il.Emit (OpCodes.Stloc_2);//new ds is now loc 2
+
+                       emitRemoveOldDataSourceHandler (il, "ValueChanged", delName, true);
+
+                       if (!string.IsNullOrEmpty (bindingDef.TargetMember)) {
+                               if (bindingDef.TwoWay) //remove handler
+                                       emitRemoveOldDataSourceHandler (il, "ValueChanged", delName, false);
+                               //test if new ds is null
+                               il.Emit (OpCodes.Ldloc_2);
+                               il.Emit (OpCodes.Brfalse, newDSIsNull);//new ds is null
+                               //test if new ds is of expected type
+                               il.Emit (OpCodes.Ldloc_2);
+                               il.Emit (OpCodes.Isinst, dsType);
+                               //il.Emit (OpCodes.Call, CompilerServices.miGetMDToken);
+                               //il.Emit (OpCodes.Ldc_I4, dsType.MetadataToken);
+                               il.Emit (OpCodes.Brfalse, newDSIsNull);
+                       }
+
+                       #region fetch initial Value
+                       if (!string.IsNullOrEmpty (bindingDef.TargetMember)) {
+                               Type mbType;
+                               MemberInfo mi = CompilerServices.GetMemberInfo (dsType, bindingDef.TargetMember, out mbType);
+                               if (mi != null) {
+                                       il.Emit (OpCodes.Ldarg_1);//load source of dataSourceChanged which is the dest instance
+                                       il.Emit (OpCodes.Ldloc_2);//load new ds
+                                       CompilerServices.emitGetMemberValue (il, dsType, mi);
+                                       if (mbType != piSource.PropertyType)
+                                               CompilerServices.emitConvert (il, mbType, piSource.PropertyType);
+                                       il.Emit (OpCodes.Callvirt, piSource.GetSetMethod ());
+                               }
+                       }
+                       #endregion
+
+                       if (!string.IsNullOrEmpty (bindingDef.TargetMember)) {
+                               il.MarkLabel (cancelInit);
+                               //check if new dataSource implement IValueChange
+                               il.Emit (OpCodes.Ldloc_2);//load new datasource
+                               il.Emit (OpCodes.Isinst, typeof (IValueChange));
+                               il.Emit (OpCodes.Brfalse, cancel);
+
+                               il.Emit (OpCodes.Ldarg_0);//load ref to this instanciator onto the stack
+                               il.Emit (OpCodes.Ldarg_1);//load datasource change source
+                               il.Emit (OpCodes.Ldloc_2);//load new datasource
+                               il.Emit (OpCodes.Ldc_I4, dmVC);//load index of dynmathod
+                               il.Emit (OpCodes.Call, CompilerServices.miDSChangeEmitHelper);
+
+                               il.MarkLabel (cancel);
+
+                               if (bindingDef.TwoWay) {
+                                       il.Emit (OpCodes.Ldarg_1);//arg1: dataSourceChange source, the origine of the binding
+                                       il.Emit (OpCodes.Ldstr, bindingDef.SourceMember);//arg2: orig member
+                                       il.Emit (OpCodes.Ldloc_2);//arg3: new datasource
+                                       il.Emit (OpCodes.Ldstr, bindingDef.TargetMember);//arg4: dest member
+                                       il.Emit (OpCodes.Call, CompilerServices.miDSReverseBinding);
+                               }
+
+                       }
+                       il.MarkLabel (newDSIsNull);
+                       il.Emit (OpCodes.Ret);
+
+                       //store dschange delegate in instatiator instance for access while instancing graphic object
+                       int delDSIndex = cachedDelegates.Count;
+                       cachedDelegates.Add (dm.CreateDelegate (CompilerServices.ehTypeDSChange, this));
+                       #endregion
+
+                       ctx.emitCachedDelegateHandlerAddition (delDSIndex, CompilerServices.eiDSChange);
+
+#if DEBUG_BINDING
+                       Debug.WriteLine("\tDataSource ValueChanged: " + delName);
+                       Debug.WriteLine("\tDataSource Changed: " + dm.Name);
+#endif
+               }
+               /// <summary>
                /// create the valuechanged handler, the datasourcechanged handler and emit event handling
                /// </summary>
                void emitDataSourceBindings(IMLContext ctx, BindingDefinition bindingDef){
@@ -1044,13 +1216,18 @@ namespace Crow.IML
 
                        il.DeclareLocal (typeof(object));//used for checking propery less bindings
                        il.DeclareLocal (typeof(MemberInfo));//used for checking propery less bindings
+                       il.DeclareLocal (typeof (object));//new datasource store, save one field access
                        System.Reflection.Emit.Label cancel = il.DefineLabel ();
                        System.Reflection.Emit.Label newDSIsNull = il.DefineLabel ();
                        System.Reflection.Emit.Label cancelInit = il.DefineLabel ();
 
                        il.Emit (OpCodes.Nop);
 
-                       emitRemoveOldDataSourceHandler(il, "ValueChanged", delName, true);
+                       il.Emit (OpCodes.Ldarg_2);//load datasource change arg
+                       il.Emit (OpCodes.Ldfld, CompilerServices.fiDSCNewDS);
+                       il.Emit (OpCodes.Stloc_2);//new ds is now loc 2
+
+                       emitRemoveOldDataSourceHandler (il, "ValueChanged", delName, true);
 
                        if (!string.IsNullOrEmpty(bindingDef.TargetMember)){
                                if (bindingDef.TwoWay){
@@ -1070,15 +1247,13 @@ namespace Crow.IML
 //                                     il.Emit (OpCodes.Call, CompilerServices.miRemEvtHdlByTarget);
 //                                     il.MarkLabel(cancelRemove);
                                }
-                               il.Emit (OpCodes.Ldarg_2);//load datasource change arg
-                               il.Emit (OpCodes.Ldfld, CompilerServices.fiDSCNewDS);
+                               il.Emit (OpCodes.Ldloc_2);
                                il.Emit (OpCodes.Brfalse, newDSIsNull);//new ds is null
                        }
 
 #region fetch initial Value
                        if (!string.IsNullOrEmpty(bindingDef.TargetMember)){
-                               il.Emit (OpCodes.Ldarg_2);//load new datasource
-                               il.Emit (OpCodes.Ldfld, CompilerServices.fiDSCNewDS);
+                               il.Emit (OpCodes.Ldloc_2); 
                                il.Emit (OpCodes.Ldstr, bindingDef.TargetMember);//load member name
                                il.Emit (OpCodes.Call, CompilerServices.miGetMembIinfoWithRefx);
                                il.Emit (OpCodes.Stloc_1);//save memberInfo
@@ -1087,8 +1262,7 @@ namespace Crow.IML
                        }
 
                        il.Emit (OpCodes.Ldarg_1);//load source of dataSourceChanged which is the dest instance
-                       il.Emit (OpCodes.Ldarg_2);//load new datasource
-                       il.Emit (OpCodes.Ldfld, CompilerServices.fiDSCNewDS);
+                       il.Emit (OpCodes.Ldloc_2);//load new datasource
                        if (!string.IsNullOrEmpty(bindingDef.TargetMember)){
                                il.Emit (OpCodes.Ldloc_1);//push mi for value fetching
                                il.Emit (OpCodes.Call, CompilerServices.miGetValWithRefx);
@@ -1100,15 +1274,13 @@ namespace Crow.IML
                        if (!string.IsNullOrEmpty(bindingDef.TargetMember)){
                                il.MarkLabel(cancelInit);
                                //check if new dataSource implement IValueChange
-                               il.Emit (OpCodes.Ldarg_2);//load new datasource
-                               il.Emit (OpCodes.Ldfld, CompilerServices.fiDSCNewDS);
+                               il.Emit (OpCodes.Ldloc_2);//load new datasource
                                il.Emit (OpCodes.Isinst, typeof(IValueChange));
                                il.Emit (OpCodes.Brfalse, cancel);
 
                                il.Emit(OpCodes.Ldarg_0);//load ref to this instanciator onto the stack
                                il.Emit (OpCodes.Ldarg_1);//load datasource change source
-                               il.Emit (OpCodes.Ldarg_2);//load new datasource
-                               il.Emit (OpCodes.Ldfld, CompilerServices.fiDSCNewDS);
+                               il.Emit (OpCodes.Ldloc_2);//load new datasource
                                il.Emit(OpCodes.Ldc_I4, dmVC);//load index of dynmathod
                                il.Emit (OpCodes.Call, CompilerServices.miDSChangeEmitHelper);
 
@@ -1117,8 +1289,7 @@ namespace Crow.IML
                                if (bindingDef.TwoWay){
                                        il.Emit (OpCodes.Ldarg_1);//arg1: dataSourceChange source, the origine of the binding
                                        il.Emit (OpCodes.Ldstr, bindingDef.SourceMember);//arg2: orig member
-                                       il.Emit (OpCodes.Ldarg_2);//arg3: new datasource
-                                       il.Emit (OpCodes.Ldfld, CompilerServices.fiDSCNewDS);
+                                       il.Emit (OpCodes.Ldloc_2);//arg3: new datasource
                                        il.Emit (OpCodes.Ldstr, bindingDef.TargetMember);//arg4: dest member
                                        il.Emit (OpCodes.Call, CompilerServices.miDSReverseBinding);
                                }
index 7db6fad5f0a2b483f0376a4031b8d2844951d699..b4d7840c6c168e31cd8504a826f2d6b460d288fa 100644 (file)
@@ -8,7 +8,7 @@ using System.Runtime.CompilerServices;
 
 namespace tests
 {
-       class MainClass : Interface
+       public class MainClass : Interface
        {
                [DllImport ("dl", CallingConvention=CallingConvention.Cdecl)]
                static extern IntPtr dlopen (string file, dlmode mode);
@@ -54,7 +54,7 @@ namespace tests
                /*[DllImport (cairoLibPath, EntryPoint="cairo_stroke")]
                [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
                public static extern void cairo_stroke_icall (IntPtr cr);*/
-
+               public string StringTest = "this is a string for testing";
 
                static MainClass app;
                public Command CMDTest;
@@ -115,9 +115,9 @@ namespace tests
                                //app.AddWidget (@"Interfaces/Divers/testFocus.crow").DataSource = app;
                                //app.AddWidget (@"Interfaces/Divers/testMenu.crow").DataSource = app;
                                //app.AddWidget (@"Interfaces/Divers/testVisibility.crow").DataSource = app;
-                               app.Load (@"Interfaces/Divers/0.crow").DataSource = app;
+                               //app.Load (@"Interfaces/Divers/0.crow").DataSource = app;
                                //app.AddWidget (@"Interfaces/Splitter/1.crow").DataSource = app;
-                               //app.AddWidget (@"Interfaces/GraphicObject/0.crow").DataSource = app;
+                               app.Load (@"Interfaces/GraphicObject/0.crow").DataSource = app;
                                //app.AddWidget (@"Interfaces/TemplatedContainer/test_Listbox.crow").DataSource = app;
 
                                /*app.instFileDlg = Crow.IML.Instantiator.CreateFromImlFragment
index 97cda8a0a4f85b133bdb89787d0e9032ca64b3b6..d608cf00a99de8595a1a62e5a5a81355c5725246 100755 (executable)
@@ -1,2 +1,4 @@
 <?xml version="1.0"?>
-<GraphicObject Background="SeaGreen"/>
\ No newline at end of file
+<VerticalStack >
+    <Label Text="{StringTest}" Background="SeaGreen" DataSourceType="MainClass"/>
+</VerticalStack>