From: Jean-Philippe Bruyère Date: Tue, 29 Jul 2025 08:12:19 +0000 (+0200) Subject: debug binding object->value type X-Git-Url: https://git.osiis.dedyn.io/?a=commitdiff_plain;h=3f16c00248623bac4c883d3c6cd43afeaaa0d630;p=jp%2Fcrow.git debug binding object->value type --- diff --git a/Crow/Crow.csproj b/Crow/Crow.csproj index 316345cf..61b83e98 100644 --- a/Crow/Crow.csproj +++ b/Crow/Crow.csproj @@ -30,7 +30,7 @@ full - $(DefineConstants);DEBUG;TRACE;_DEBUG_BINDING;_DEBUG_CLIP_RECTANGLE + $(DefineConstants);DEBUG;TRACE;_DEBUG_BINDING;_DEBUG_BINDING_FUNC_CALLS;_DEBUG_CLIP_RECTANGLE true diff --git a/Crow/src/IML/CompilerServices.cs b/Crow/src/IML/CompilerServices.cs index 2cea823d..c288e07a 100644 --- a/Crow/src/IML/CompilerServices.cs +++ b/Crow/src/IML/CompilerServices.cs @@ -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; + } /// /// Emit MSIL for conversion from orig type to dest type /// 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) diff --git a/Crow/src/IML/Instantiator.cs b/Crow/src/IML/Instantiator.cs index dc3e77da..c0492e41 100644 --- a/Crow/src/IML/Instantiator.cs +++ b/Crow/src/IML/Instantiator.cs @@ -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); } /// diff --git a/Crow/src/Widgets/Widget.cs b/Crow/src/Widgets/Widget.cs index 6f20a54b..1a7f1e7b 100644 --- a/Crow/src/Widgets/Widget.cs +++ b/Crow/src/Widgets/Widget.cs @@ -552,7 +552,7 @@ namespace Crow /// If enabled, resulting bitmap of graphic object is cached /// speeding up rendering of complex object. Default is enabled. /// - [DesignCategory ("Behavior")][DefaultValue(false)] + [DesignCategory ("Behaviour")][DefaultValue(false)] public virtual bool CacheEnabled { get => cacheEnabled; set {