From: jpbruyere Date: Thu, 22 Dec 2016 09:08:15 +0000 (+0100) Subject: Template handler binding, name resolution, IsTemplateBinding property in X-Git-Tag: v0.5.1~63^2~16 X-Git-Url: https://git.osiis.dedyn.io/?a=commitdiff_plain;h=73bea0870454ab6d495378cefb31c000f0441966;p=jp%2Fcrow.git Template handler binding, name resolution, IsTemplateBinding property in BindingDefinition class modifié : src/CompilerServices/CompilerServices.cs modifié : src/IML/BindingDefinition.cs modifié : src/IML/Context.cs modifié : src/Instantiator.cs --- diff --git a/src/CompilerServices/CompilerServices.cs b/src/CompilerServices/CompilerServices.cs index ba824c62..16ad5d8e 100644 --- a/src/CompilerServices/CompilerServices.cs +++ b/src/CompilerServices/CompilerServices.cs @@ -48,7 +48,7 @@ namespace Crow internal static EventInfo eiDSChange = typeof (GraphicObject).GetEvent ("DataSourceChanged"); internal static MethodInfo miInvokeDSChange = eiDSChange.EventHandlerType.GetMethod ("Invoke"); - internal static Type [] argsDSChange = {typeof (object), typeof (object), miInvokeDSChange.GetParameters () [1].ParameterType }; + internal static Type [] argsBoundDSChange = {typeof (object), typeof (object), miInvokeDSChange.GetParameters () [1].ParameterType }; internal static FieldInfo fiDSCNewDS = typeof (DataSourceChangeEventArgs).GetField ("NewDataSource"); internal static MethodInfo miCreateBoundDelegate = typeof(DynamicMethod). diff --git a/src/IML/BindingDefinition.cs b/src/IML/BindingDefinition.cs index 19a54d09..2c3fecdc 100644 --- a/src/IML/BindingDefinition.cs +++ b/src/IML/BindingDefinition.cs @@ -51,6 +51,7 @@ namespace Crow.IML #endregion public bool IsDataSourceBinding { get { return TargetNA == null; }} + public bool IsTemplateBinding { get { return IsDataSourceBinding ? false : TargetNA.Count == 0; }} public bool HasUnresolvedTargetName { get { return !string.IsNullOrEmpty(TargetName); }} /// diff --git a/src/IML/Context.cs b/src/IML/Context.cs index 104633c6..393bab21 100644 --- a/src/IML/Context.cs +++ b/src/IML/Context.cs @@ -99,8 +99,10 @@ namespace Crow.IML } public void ResolveNames (){ foreach (BindingDefinition bd in UnresolvedTargets) { - if (!Names.ContainsKey (bd.TargetName)) - throw new Exception ("Target Name '" + bd.TargetName + "' not found"); + if (!Names.ContainsKey (bd.TargetName)) { + System.Diagnostics.Debug.WriteLine ("Target Name '" + bd.TargetName + "' not found"); + continue; + } NodeAddress resolvedNA = null; foreach (NodeAddress na in Names[bd.TargetName]) { bool naMatch = true; @@ -116,10 +118,11 @@ namespace Crow.IML } } if (resolvedNA == null) - throw new Exception ("Target Name '" + bd.TargetName + "' not found"); - - bd.ResolveTargetName (resolvedNA); - StorePropertyBinding (bd); + System.Diagnostics.Debug.WriteLine ("Target Name '" + bd.TargetName + "' not found"); + else { + bd.ResolveTargetName (resolvedNA); + StorePropertyBinding (bd); + } } } diff --git a/src/Instantiator.cs b/src/Instantiator.cs index 0ff9e4de..90cb8045 100644 --- a/src/Instantiator.cs +++ b/src/Instantiator.cs @@ -93,6 +93,7 @@ namespace Crow List dsValueChangedDynMeths = new List(); List cachedDelegates = new List(); + List templateCachedDelegateIndices = new List();//store indices of template delegate to be handled by root parentChanged event Dictionary bindingDelegates = new Dictionary();//valuechanged del Dictionary bindingInitializer = new Dictionary();//initialize with actual values of binding origine Delegate templateBinding; @@ -108,6 +109,10 @@ namespace Crow emitLoader (reader, ctx); ctx.nodesStack.Pop (); + foreach (int idx in templateCachedDelegateIndices) + ctx.emitCachedDelegateHandlerAddition(idx, typeof(GraphicObject).GetEvent("ParentChanged")); + + ctx.ResolveNames (); emitBindingDelegates (ctx); @@ -455,6 +460,10 @@ namespace Crow } #endregion + /// + /// Emits in the instantiator ctx the search for normal (in the current graphic tree) property binding delegates for actual element, + /// and add event if found. + /// void emitCheckAndBindValueChanged(Context ctx){ System.Reflection.Emit.Label labContinue = ctx.il.DefineLabel (); string strNA = ctx.CurrentNodeAddress.ToString (); @@ -497,7 +506,6 @@ namespace Crow Debug.WriteLine ("\tCompile Event Source "); #endif - #region Retrieve EventHandler parameter type MethodInfo evtInvoke = sourceEvent.EventHandlerType.GetMethod ("Invoke"); ParameterInfo [] evtParams = evtInvoke.GetParameters (); @@ -509,10 +517,8 @@ namespace Crow typeof(void), args, true); - #region IL generation NodeAddress currentNode = ctx.CurrentNodeAddress; - string strNA = currentNode.ToString(); ILGenerator il = dm.GetILGenerator (256); il.Emit (OpCodes.Nop); @@ -623,6 +629,9 @@ namespace Crow NodeAddress currentNode = ctx.CurrentNodeAddress; BindingDefinition bindingDef = splitBindingExp (currentNode, sourceEvent.Name, expression); + if (bindingDef.HasUnresolvedTargetName) + return; + string bindOnEventName = null; if (bindingDef.TargetNA == null)//datasource handler @@ -634,9 +643,10 @@ namespace Crow //we need to bind datasource method to source event DynamicMethod dm = new DynamicMethod ("dyn_dschangedForHandler", typeof (void), - CompilerServices.argsDSChange, true); + CompilerServices.argsBoundDSChange, true); ILGenerator il = dm.GetILGenerator (256); + System.Reflection.Emit.Label cancel = il.DefineLabel (); il.DeclareLocal (typeof(MethodInfo));//used to cancel binding if method doesn't exist @@ -645,14 +655,19 @@ namespace Crow //fetch method in datasource and test if it exist il.Emit (OpCodes.Ldarg_2);//load new datasource il.Emit (OpCodes.Ldfld, CompilerServices.fiDSCNewDS); + il.Emit (OpCodes.Brfalse, cancel);//cancel if new datasource is null + il.Emit (OpCodes.Ldarg_2);//load new datasource + il.Emit (OpCodes.Ldfld, CompilerServices.fiDSCNewDS); il.Emit (OpCodes.Ldstr, bindingDef.TargetMember);//load handler method name il.Emit (OpCodes.Call, typeof(CompilerServices).GetMethod("getMethodInfoWithReflexion", BindingFlags.Static | BindingFlags.Public)); il.Emit (OpCodes.Stloc_0);//save MethodInfo il.Emit (OpCodes.Ldloc_0);//push mi for test if null - System.Reflection.Emit.Label methodNotFound = il.DefineLabel (); - il.Emit (OpCodes.Brfalse, methodNotFound); + + il.Emit (OpCodes.Brfalse, cancel); il.Emit (OpCodes.Ldarg_1);//load datasource change source where the event handler is as 1st arg of handler.add + if (bindingDef.IsTemplateBinding)//fetch source instance with address + emitGetInstance (il, bindingDef.SourceNA); //loat handlerType of sourceEvent to create delegate (1st arg) il.Emit(OpCodes.Ldtoken, sourceEvent.EventHandlerType); @@ -665,14 +680,21 @@ namespace Crow new Type[] {typeof(Type), typeof(object), typeof(MethodInfo)}));//create bound delegate il.Emit(OpCodes.Callvirt, sourceEvent.AddMethod);//call add event - il.MarkLabel(methodNotFound); + System.Reflection.Emit.Label finish = il.DefineLabel (); + il.Emit (OpCodes.Br, finish); + il.MarkLabel (cancel); + il.EmitWriteLine (sourcePath + ": Handler method not found: " + bindingDef.TargetMember); + il.MarkLabel (finish); 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)); - ctx.emitCachedDelegateHandlerAddition(delDSIndex, typeof(GraphicObject).GetEvent(bindOnEventName)); + if (bindingDef.TargetNA == null) + ctx.emitCachedDelegateHandlerAddition(delDSIndex, typeof(GraphicObject).GetEvent("DataSourceChanged")); + else //template handler binding + templateCachedDelegateIndices.Add(delDSIndex); } } /// @@ -697,7 +719,7 @@ namespace Crow //create parentchanged dyn meth in parallel to have only one loop over bindings DynamicMethod dmPC = new DynamicMethod ("dyn_InitAndParentChanged", typeof (void), - CompilerServices.argsDSChange, true); + CompilerServices.argsBoundDSChange, true); ILGenerator ilPC = dmPC.GetILGenerator (256); il.Emit (OpCodes.Nop); @@ -970,7 +992,7 @@ namespace Crow //dm is bound to the instanciator instance to have access to cached dyn meth and delegates dm = new DynamicMethod ("dyn_dschanged", typeof (void), - CompilerServices.argsDSChange, true); + CompilerServices.argsBoundDSChange, true); il = dm.GetILGenerator (256); @@ -1073,9 +1095,9 @@ namespace Crow if (destType == typeof(string)) il.Emit (OpCodes.Callvirt, CompilerServices.miObjToString); else if (origType.IsValueType) { - if (destType != origType) + if (destType != origType) { il.Emit (OpCodes.Callvirt, CompilerServices.GetConvertMethod (destType)); - else + }else il.Emit (OpCodes.Unbox_Any, destType);//TODO:double check this } else { if (origType.IsAssignableFrom(destType))