]> O.S.I.I.S - jp/crow.git/commitdiff
debug binding object->value type
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Tue, 29 Jul 2025 08:12:19 +0000 (10:12 +0200)
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Tue, 29 Jul 2025 08:12:19 +0000 (10:12 +0200)
Crow/Crow.csproj
Crow/src/IML/CompilerServices.cs
Crow/src/IML/Instantiator.cs
Crow/src/Widgets/Widget.cs

index 316345cf6ac3f16528e9ad1523df8314ac0b9780..61b83e98ad93575f3bcd004b98b140be2b515931 100644 (file)
@@ -30,7 +30,7 @@
        </PropertyGroup>
        <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
                <DebugType>full</DebugType>
-               <DefineConstants>$(DefineConstants);DEBUG;TRACE;_DEBUG_BINDING;_DEBUG_CLIP_RECTANGLE</DefineConstants>
+               <DefineConstants>$(DefineConstants);DEBUG;TRACE;_DEBUG_BINDING;_DEBUG_BINDING_FUNC_CALLS;_DEBUG_CLIP_RECTANGLE</DefineConstants>
                <CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
        </PropertyGroup>
        <ItemGroup Condition="$(TargetFramework.StartsWith('netstandard'))">
index 2cea823d01741da4d7fbc91c2dc451d112e4d2b8..c288e07af8c8decb5ed6067be71b7199bb1f2d8b 100644 (file)
@@ -548,11 +548,30 @@ namespace Crow.IML
                                return;
                        }
                }
-
+               static bool emitParse(ILGenerator il, Type destType) {
+                       //search dest type for parse method
+                       MethodInfo miParse = destType.GetMethod
+                                                                       ("Parse", BindingFlags.Static | BindingFlags.Public,
+                                                                               Type.DefaultBinder, new Type [] { typeof (string) }, null);
+                       if (miParse == null) {
+                               //TODO:find parse for enums destTypes
+                               if (destType.IsEnum) {
+                                       il.Emit (OpCodes.Ldtoken, destType);//push destination property type for testing
+                                       il.Emit (OpCodes.Call, CompilerServices.miGetTypeFromHandle);
+                                       il.Emit (OpCodes.Call, CompilerServices.miParseEnumInversedParams);
+                                       il.Emit (OpCodes.Unbox_Any, destType);
+                               } else
+                                       return false;
+                       }else
+                               il.Emit (OpCodes.Call, miParse);
+                       return true;
+               }
                /// <summary>
                /// Emit MSIL for conversion from orig type to dest type
                /// </summary>
                internal static void emitConvert(ILGenerator il, Type origType, Type destType){
+                       //Console.WriteLine ($"emitConvert: {origType.FullName} -> {destType.FullName}");
+                       //il.EmitWriteLine ($"convert: {origType.FullName} -> {destType.FullName}");
                        if (destType == typeof(object))
                                return;
                        if (destType == typeof (string)) {
@@ -596,32 +615,30 @@ namespace Crow.IML
                                        }
                                } else
                                        il.Emit (OpCodes.Unbox_Any, destType);//TODO:double check this
+                       } else if (destType.IsValueType && origType == typeof(object)){
+                               System.Reflection.Emit.Label labContinue = il.DefineLabel ();
+                               System.Reflection.Emit.Label emitFinish = il.DefineLabel ();
+                               il.Emit (OpCodes.Dup);
+                               il.Emit (OpCodes.Isinst, typeof(string));
+                               il.Emit (OpCodes.Brfalse, labContinue);
+                               emitParse (il, destType);
+                               il.Emit (OpCodes.Br, emitFinish);
+                               il.MarkLabel (labContinue);
+                               il.Emit (OpCodes.Unbox_Any, destType);//TODO:double check this
+                               il.MarkLabel (emitFinish);
                        } else {
                                if (destType.IsAssignableFrom (origType))
                                        il.Emit (OpCodes.Castclass, destType);
                                else {
                                        if (origType == typeof (string)) {
-                                               //search dest type for parse method
-                                               MethodInfo miParse = destType.GetMethod
-                                                                                               ("Parse", BindingFlags.Static | BindingFlags.Public,
-                                                                                                       Type.DefaultBinder, new Type [] { typeof (string) }, null);
-                                               if (miParse == null) {
-                                                       //TODO:find parse for enums destTypes
-                                                       if (destType.IsEnum) {
-                                                               il.Emit (OpCodes.Ldtoken, destType);//push destination property type for testing
-                                                               il.Emit (OpCodes.Call, CompilerServices.miGetTypeFromHandle);
-                                                               il.Emit (OpCodes.Call, CompilerServices.miParseEnumInversedParams);
-                                                               il.Emit (OpCodes.Unbox_Any, destType);
-                                                       } else
-                                                               throw new Exception ("no Parse method found for: " + destType.FullName);
-                                               }else
-                                                       il.Emit (OpCodes.Call, miParse);
+                                               if (!emitParse (il, destType))
+                                                       throw new Exception ("no Parse method found for: " + destType.FullName);
                                        }
                                        //implicit conversion can't be defined from or to object base class,
                                        //so we will check if object underlying type is one of the implicit converter of destType
                                        else if (origType == typeof (object)) {//test all implicit converter to destType on obj
+                                               System.Reflection.Emit.Label emitFinish = il.DefineLabel ();
                                                System.Reflection.Emit.Label emitTestNextImpOp;
-                                               System.Reflection.Emit.Label emitImpOpFound = il.DefineLabel ();
                                                foreach (MethodInfo mi in destType.GetMethods (BindingFlags.Public | BindingFlags.Static)) {
                                                        if (mi.Name == "op_Implicit") {
                                                                if (mi.GetParameters () [0].ParameterType == destType)
@@ -636,13 +653,13 @@ namespace Crow.IML
                                                                        il.Emit (OpCodes.Isinst, mi.GetParameters () [0].ParameterType);
 
                                                                il.Emit (OpCodes.Call, mi);
-                                                               il.Emit (OpCodes.Br, emitImpOpFound);
+                                                               il.Emit (OpCodes.Br, emitFinish);
 
                                                                il.MarkLabel (emitTestNextImpOp);
                                                        }
                                                }
                                                //il.Emit (OpCodes.Br, emitImpOpNotFound);
-                                               il.MarkLabel (emitImpOpFound);
+                                               il.MarkLabel (emitFinish);
                                        } else {//search both orig and dest types for implicit operators
                                                MethodInfo miIO = getImplicitOp (origType, destType);
                                                if (miIO != null)
index dc3e77da57a341fd3fd3f37e12bd7a8bd8a5d76b..c0492e41cb3eb046269b1fddfca1dfebe654c697 100644 (file)
@@ -1208,7 +1208,7 @@ namespace Crow.IML {
                        dm = new DynamicMethod (dschangeddelname,
                                typeof (void),
                                CompilerServices.argsBoundDSChange, true);
-
+                       
                        il = dm.GetILGenerator (64);
 
                        il.DeclareLocal (typeof (object));//used for checking propery less bindings
@@ -1216,7 +1216,7 @@ namespace Crow.IML {
                        il.DeclareLocal (typeof (object));//new datasource store, save one field access
                        Label cancel = il.DefineLabel ();
                        Label newDSIsNull = il.DefineLabel ();
-                       Label cancelInit = il.DefineLabel ();
+                       //Label cancelInit = il.DefineLabel ();
 #if DEBUG_BINDING
                        il.EmitWriteLine ($"DYN Called => {dschangeddelname}");
 #endif
@@ -1236,8 +1236,6 @@ namespace Crow.IML {
                                //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);
 #if DEBUG_BINDING
                                il.EmitWriteLine ($"\tNew ds is of expected type: {dsType}");
@@ -1263,7 +1261,7 @@ namespace Crow.IML {
                        #endregion
 
                        if (!string.IsNullOrEmpty (bindingDef.TargetMember)) {
-                               il.MarkLabel (cancelInit);
+                               //il.MarkLabel (cancelInit);
                                //check if new dataSource implement IValueChange
                                il.Emit (OpCodes.Ldloc_2);//load new datasource
                                il.Emit (OpCodes.Isinst, typeof (IValueChange));
@@ -1296,18 +1294,18 @@ namespace Crow.IML {
                        //store dschange delegate in instatiator instance for access while instancing graphic object
                        int delDSIndex = cachedDelegates.Count;
 
-                       //Int32 fiLength = (Int32)il.GetType ().GetField ("code_len", BindingFlags.Instance | BindingFlags.NonPublic).GetValue (il);
-                       //byte [] bytes = (byte[])il.GetType ().GetField ("code", BindingFlags.Instance | BindingFlags.NonPublic).GetValue (il);
-
-                       cachedDelegates.Add (dm.CreateDelegate (CompilerServices.ehTypeDSChange, this));
-                       #endregion
-
-                       ctx.emitCachedDelegateHandlerAddition (delDSIndex, CompilerServices.eiDSChange);
+                       //Int32 fiLength = (Int32)Type.GetType("System.Reflection.Emit.ILGenerator").GetField("m_length",  BindingFlags.Instance | BindingFlags.NonPublic).GetValue (il);
+                       //byte [] bytes = (byte[])Type.GetType("System.Reflection.Emit.ILGenerator").GetField ("m_ILStream", BindingFlags.Instance | BindingFlags.NonPublic).GetValue (il);
 
 #if DEBUG_BINDING
                        Console.WriteLine("\tDataSource ValueChanged: " + delName);
                        Console.WriteLine("\tDataSource Changed: " + dm.Name);
 #endif
+
+                       cachedDelegates.Add (dm.CreateDelegate (CompilerServices.ehTypeDSChange, this));
+                       #endregion
+
+                       ctx.emitCachedDelegateHandlerAddition (delDSIndex, CompilerServices.eiDSChange);
                }
 
                /// <summary>
index 6f20a54bde5b95521c96579014098fcccbb99eba..1a7f1e7ba0befe6410b2443795a17b4c8f91b0c9 100644 (file)
@@ -552,7 +552,7 @@ namespace Crow
                /// If enabled, resulting bitmap of graphic object is cached
                /// speeding up rendering of complex object. Default is enabled.
                /// </summary>
-               [DesignCategory ("Behavior")][DefaultValue(false)]
+               [DesignCategory ("Behaviour")][DefaultValue(false)]
                public virtual bool CacheEnabled {
                        get => cacheEnabled;
                        set {