aboutsummaryrefslogtreecommitdiffstatsci
path: root/src
diff options
context:
space:
mode:
authorjpbruyere <jp.bruyere@hotmail.com>2016-12-22 10:08:15 +0100
committerjpbruyere <jp.bruyere@hotmail.com>2016-12-22 10:08:15 +0100
commit73bea0870454ab6d495378cefb31c000f0441966 (patch)
treea8a9f7ee186aee75bda6c556d7217b502b0a81a2 /src
parent971cc1b46896f42553874396cae104b43370280b (diff)
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
Diffstat (limited to 'src')
-rw-r--r--src/CompilerServices/CompilerServices.cs2
-rw-r--r--src/IML/BindingDefinition.cs1
-rw-r--r--src/IML/Context.cs15
-rw-r--r--src/Instantiator.cs46
4 files changed, 45 insertions, 19 deletions
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); }}
/// <summary>
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<DynamicMethod> dsValueChangedDynMeths = new List<DynamicMethod>();
List<Delegate> cachedDelegates = new List<Delegate>();
+ List<int> templateCachedDelegateIndices = new List<int>();//store indices of template delegate to be handled by root parentChanged event
Dictionary<string, Delegate> bindingDelegates = new Dictionary<string, Delegate>();//valuechanged del
Dictionary<string, Delegate> bindingInitializer = new Dictionary<string, Delegate>();//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
+ /// <summary>
+ /// 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.
+ /// </summary>
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);
}
}
/// <summary>
@@ -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))