ctx.il.MarkLabel (labContinue);
}
- void readPropertyBinding (Context ctx, string sourceMember, string expression)
- {
- MemberAddress targetMember;
- NodeAddress target;
-
- string memberName = null;
- bool twoWay = false;
-
- //if binding exp = '{}' => binding is done on datasource
- if (string.IsNullOrEmpty (expression))
- return;
+ /// <summary>
+ /// Splits the binding expression
+ /// </summary>
+ /// <returns><c>true</c>, if it's a two ways binding, <c>false</c> otherwise.</returns>
+ /// <param name="currentNode">current node address</param>
+ /// <param name="expression">Binding expression</param>
+ /// <param name="na">node address, null if on dataSource, count=0 if template binding outside current graphic tree</param>
+ /// <param name="memberName">Member name.</param>
+ /// <param name="namedNode">Named node.</param>
+ bool splitBindingExp(NodeAddress currentNode, string expression, out NodeAddress na, out string memberName, out string namedNode){
+ namedNode = "";
+ if (string.IsNullOrEmpty (expression)) {
+ na = null;
+ memberName = "";
+ } else {
+ string[] bindingExp = expression.Split ('/');
- if (expression.StartsWith ("²")) {
- expression = expression.Substring (1);
- twoWay = true;
- }
+ if (bindingExp.Length == 1)
+ na = null;
+ else
+ na = getNodeAdressFromBindingExp (currentNode, bindingExp);
- string[] bindingExp = expression.Split ('/');
+ string [] bindTrg = bindingExp.Last().Split ('.');
- if (bindingExp.Length == 1) {
- //datasource binding
- processDataSourceBinding (ctx, sourceMember, bindingExp [0]);
- return;
+ if (bindTrg.Length == 1)
+ memberName = bindTrg [0];
+ else if (bindTrg.Length == 2) {
+ //named target
+ namedNode = bindTrg[0];
+ memberName = bindTrg [1];
+ } else
+ throw new Exception ("Syntax error in binding, expected 'go dot member'");
}
- NodeAddress currentNode = ctx.CurrentNodeAddress;
- NodeAddress targetNA = getNodeAdressFromBindingExp (currentNode, bindingExp);
+ return expression.StartsWith ("²");
+ }
- string [] bindTrg = bindingExp.Last().Split ('.');
+ void readPropertyBinding (Context ctx, string sourceMember, string expression)
+ {
+ string memberName, namedNode;
+ NodeAddress currentNode = ctx.CurrentNodeAddress, targetNA;
- if (bindTrg.Length == 1)
- memberName = bindTrg [0];
- else if (bindTrg.Length == 2) {
- //named target
- //TODO:
+ bool twoWay = splitBindingExp (currentNode, expression, out targetNA, out memberName, out namedNode);
- memberName = bindTrg [1];
+ if (targetNA == null) {//bind on data source
+ processDataSourceBinding (ctx, sourceMember, memberName);
return;
- } else
- throw new Exception ("Syntax error in binding, expected 'go dot member'");
+ }
+
+// //if binding exp = '{}' => binding is done on datasource
+// if (string.IsNullOrEmpty (expression))
+// return;
+//
+// if (expression.StartsWith ("²")) {
+// expression = expression.Substring (1);
+// twoWay = true;
+// }
+//
+// string[] bindingExp = expression.Split ('/');
+//
+// if (bindingExp.Length == 1) {
+// //datasource binding
+// processDataSourceBinding (ctx, sourceMember, bindingExp [0]);
+// return;
+// }
+//
+// NodeAddress currentNode = ctx.CurrentNodeAddress;
+// NodeAddress targetNA = getNodeAdressFromBindingExp (currentNode, bindingExp);
+//
+// string [] bindTrg = bindingExp.Last().Split ('.');
+//
+// if (bindTrg.Length == 1)
+// memberName = bindTrg [0];
+// else if (bindTrg.Length == 2) {
+// //named target
+// //TODO:
+//
+// memberName = bindTrg [1];
+// return;
+// } else
+// throw new Exception ("Syntax error in binding, expected 'go dot member'");
Dictionary<string, List<MemberAddress>> nodeBindings = null;
if (ctx.Bindings.ContainsKey (targetNA))
if (!nodeBindings.ContainsKey (memberName))
nodeBindings [memberName] = new List<MemberAddress> ();
nodeBindings [memberName].Add (new MemberAddress (currentNode, sourceMember));
-
- //
-// if (tmpTarget == null) {
-// #if DEBUG_BINDING
-// Debug.WriteLine ("\tBinding Target not found => " + this.ToString());
-// #endif
-// return false;
-// }
-//
-// Target = new MemberReference (tmpTarget);
-// }
-//
-// if (Target.TryFindMember (memberName)) {
-// if (TwoWayBinding) {
-// // IBindable source = Target.Instance as IBindable;
-// // if (source == null)
-// // throw new Exception (Source.Instance + " does not implement IBindable for 2 way bindings");
-// // source.Bindings.Add (new Binding (Target, Source));
-// }
-// }
- #if DEBUG_BINDING
- else
- Debug.WriteLine ("Property less binding: " + Target + expression);
- #endif
}
/// <summary>
/// Gets the node adress from binding expression splitted with '/' starting at a given node
ilPC.Emit (OpCodes.Ldloc_1);//push mi for value fetching
ilPC.Emit (OpCodes.Call, typeof(CompilerServices).GetMethod("getValueWithReflexion", BindingFlags.Static | BindingFlags.Public));
- Type dstType = ma.Property.PropertyType;
- if (dstType == typeof (string)){
- il.Emit (OpCodes.Callvirt, CompilerServices.miObjToString);
- ilPC.Emit (OpCodes.Callvirt, CompilerServices.miObjToString);
- }else if (dstType.IsValueType) {
- il.Emit (OpCodes.Unbox_Any, dstType);
- ilPC.Emit (OpCodes.Unbox_Any, dstType);
- }else{
- il.Emit (OpCodes.Castclass, dstType);
- ilPC.Emit (OpCodes.Castclass, dstType);
- }
+ emitConvert (il, ma.Property.PropertyType);
+ emitConvert (ilPC, ma.Property.PropertyType);
il.Emit (OpCodes.Callvirt, ma.Property.GetSetMethod());
ilPC.Emit (OpCodes.Callvirt, ma.Property.GetSetMethod());
#endregion
#region destination member affectations
- Type origineType = origineNodeType.GetProperty (bindingCase.Key).PropertyType;
+ PropertyInfo piOrig = origineNodeType.GetProperty (bindingCase.Key);
+ Type origineType = null;
+ if (piOrig != null)
+ origineType = piOrig.PropertyType;
+
foreach (MemberAddress ma in bindingCase.Value) {
- //for initialisation dynmeth, load current instance
- ilInit.Emit(OpCodes.Ldarg_0);
//first we have to load destination instance onto the stack, it is access
//with graphic tree functions deducted from nodes topology
il.Emit (OpCodes.Ldarg_0);//load source instance of ValueChanged event
NodeAddress destination = ma.Address;
emitGetInstance (il, origine, destination);
- emitGetInstance (ilInit, origine, destination);
- //init dynmeth: load actual value
- ilInit.Emit (OpCodes.Ldarg_0);
- ilInit.Emit (OpCodes.Callvirt, origineNodeType.GetProperty (bindingCase.Key).GetGetMethod());
+ if (origineType != null){//prop less binding, no init requiered
+ //for initialisation dynmeth, load current instance
+ ilInit.Emit(OpCodes.Ldarg_0);
+ emitGetInstance (ilInit, origine, destination);
+ //init dynmeth: load actual value
+ ilInit.Emit (OpCodes.Ldarg_0);
+ ilInit.Emit (OpCodes.Callvirt, origineNodeType.GetProperty (bindingCase.Key).GetGetMethod());
+ }
//load new value
il.Emit (OpCodes.Ldarg_1);
il.Emit (OpCodes.Ldfld, typeof (ValueChangeEventArgs).GetField ("NewValue"));
- if (origineType != ma.Property.PropertyType)//no unboxing required
- emitConvert (ilInit, origineType, ma.Property.PropertyType);
- emitConvert (il, origineType, ma.Property.PropertyType);//unboxing required
+ if (origineType == null)//property less binding
+ emitConvert (il, ma.Property.PropertyType);
+ else {
+ if (origineType != ma.Property.PropertyType)//no unboxing required
+ emitConvert (ilInit, origineType, ma.Property.PropertyType);
+ emitConvert (il, origineType, ma.Property.PropertyType);//unboxing required
- //set value
- ilInit.Emit (OpCodes.Callvirt, ma.Property.GetSetMethod());
- il.Emit (OpCodes.Callvirt, ma.Property.GetSetMethod());
+ ilInit.Emit (OpCodes.Callvirt, ma.Property.GetSetMethod());//set init value
+ }
+ il.Emit (OpCodes.Callvirt, ma.Property.GetSetMethod());//set value on value changes
}
#endregion
}else
il.Emit (OpCodes.Castclass, destType);
}
+ void emitConvert(ILGenerator il, Type dstType){
+ if (dstType == typeof (string))
+ il.Emit (OpCodes.Callvirt, CompilerServices.miObjToString);
+ else if (dstType.IsValueType)
+ il.Emit (OpCodes.Unbox_Any, dstType);
+ else
+ il.Emit (OpCodes.Castclass, dstType);
+ }
void emitConvertWorking(ILGenerator il, Type sourceValueType){
if (sourceValueType == typeof (string)) {
il.Emit (OpCodes.Callvirt, CompilerServices.miObjToString);