public void ResolveName(BindingDefinition bd) { if (!Names.ContainsKey(bd.TargetName)) { throw new Exception("Target Name '" + bd.TargetName + "' not found"); } NodeAddress resolvedNA = null; foreach (NodeAddress na in Names[bd.TargetName]) { bool naMatch = true; for (int i = 0; i < bd.TargetNA.Count; i++) { if (bd.TargetNA [i] != na [i]) { naMatch = false; break; } } if (naMatch) { resolvedNA = na; break; } } if (resolvedNA == null) { throw new Exception("Target Name '" + bd.TargetName + "' not found"); } bd.ResolveTargetName(resolvedNA); }
public void StorePropertyBinding(BindingDefinition bindDef) { if (bindDef.HasUnresolvedTargetName) { UnresolvedTargets.Add(bindDef); return; } StorePropertyBinding(bindDef.TargetNA, bindDef.TargetMember, bindDef.SourceNA, bindDef.SourceMember); if (bindDef.TwoWay) { StorePropertyBinding(bindDef.SourceNA, bindDef.SourceMember, bindDef.TargetNA, bindDef.TargetMember); } }
/// <summary> /// get BindingDefinition from binding expression /// </summary> public BindingDefinition GetBindingDef(string sourceMember, string expression) { BindingDefinition bindingDef = new BindingDefinition(this, sourceMember); if (string.IsNullOrEmpty(expression)) { return(bindingDef); } else { if (expression.StartsWith("²")) { bindingDef.TwoWay = true; expression = expression.Substring(1); } string exp = expression; bindingDef.TargetNA = this.ResolveExpression(ref exp); string [] bindTrg = exp.Split('.'); if (bindTrg.Length == 0) { throw new Exception("invalid binding expression: " + expression); } if (bindTrg.Length == 1) { bindingDef.TargetMember = bindTrg [0]; } else { if (!string.IsNullOrEmpty(bindTrg[0])) //searchByName { bindingDef.TargetName = bindTrg[0]; } bindingDef.TargetMember = exp.Substring(bindTrg[0].Length + 1); } } return(bindingDef); }
public void StorePropertyBinding(BindingDefinition bindDef) { if (bindDef.HasUnresolvedTargetName) { UnresolvedTargets.Add (bindDef); return; } StorePropertyBinding (bindDef.TargetNA, bindDef.TargetMember, bindDef.SourceNA, bindDef.SourceMember); if (bindDef.TwoWay) StorePropertyBinding (bindDef.SourceNA, bindDef.SourceMember, bindDef.TargetNA, bindDef.TargetMember); }
public void ResolveName(BindingDefinition bd) { if (!Names.ContainsKey (bd.TargetName)) throw new Exception ("Target Name '" + bd.TargetName + "' not found"); NodeAddress resolvedNA = null; foreach (NodeAddress na in Names[bd.TargetName]) { bool naMatch = true; for (int i = 0; i < bd.TargetNA.Count; i++) { if (bd.TargetNA [i] != na [i]) { naMatch = false; break; } } if (naMatch) { resolvedNA = na; break; } } if (resolvedNA == null) throw new Exception ("Target Name '" + bd.TargetName + "' not found"); bd.ResolveTargetName (resolvedNA); }
/// <summary> /// Splits the binding expression /// </summary> /// <returns><c>true</c>, if it's a two way binding, <c>false</c> otherwise.</returns> /// <param name="sourceNA">Source Node address</param> /// <param name="expression">Expression.</param> /// <param name="targetNA">Target Node Address</param> /// <param name="targetMember">Target member name</param> /// <param name="targetName">Target node name</param> BindingDefinition splitBindingExp(NodeAddress sourceNA, string sourceMember, string expression) { BindingDefinition bindingDef = new BindingDefinition(sourceNA, sourceMember); if (string.IsNullOrEmpty (expression)) { return bindingDef; } else { if (expression.StartsWith ("²")) { bindingDef.TwoWay = true; expression = expression.Substring (1); } string[] bindingExp = expression.Split ('/'); if (bindingExp.Length > 1) bindingDef.TargetNA = CompilerServices.getNodeAdressFromBindingExp (sourceNA, bindingExp); string [] bindTrg = bindingExp.Last().Split ('.'); if (bindTrg.Length == 1) bindingDef.TargetMember = bindTrg [0]; else if (bindTrg.Length == 2) { //named target bindingDef.TargetName = bindTrg[0]; bindingDef.TargetMember = bindTrg [1]; } else throw new Exception ("Syntax error in binding, expected 'go dot member'"); } return bindingDef; }
/// <summary> /// create the valuechanged handler, the datasourcechanged handler and emit event handling /// </summary> void emitDataSourceBindings(Context ctx, BindingDefinition bindingDef) { DynamicMethod dm = null; ILGenerator il = null; int dmVC = 0; PropertyInfo piSource = ctx.CurrentNodeType.GetProperty(bindingDef.SourceMember); //if no dataSource member name is provided, valuechange is not handle and datasource change //will be used as origine value string delName = "dyn_DSvalueChanged" + NewId; if (!string.IsNullOrEmpty(bindingDef.TargetMember)){ #region create valuechanged method dm = new DynamicMethod (delName, typeof (void), CompilerServices.argsBoundValueChange, true); il = dm.GetILGenerator (256); System.Reflection.Emit.Label endMethod = il.DefineLabel (); il.DeclareLocal (CompilerServices.TObject); il.Emit (OpCodes.Nop); //load value changed member name onto the stack il.Emit (OpCodes.Ldarg_2); il.Emit (OpCodes.Ldfld, CompilerServices.fiVCMbName); //test if it's the expected one il.Emit (OpCodes.Ldstr, bindingDef.TargetMember); il.Emit (OpCodes.Ldc_I4_4);//StringComparison.Ordinal il.Emit (OpCodes.Callvirt, CompilerServices.stringEquals); il.Emit (OpCodes.Brfalse, endMethod); //set destination member with valueChanged new value //load destination ref il.Emit (OpCodes.Ldarg_0); //load new value onto the stack il.Emit (OpCodes.Ldarg_2); il.Emit (OpCodes.Ldfld, CompilerServices.fiVCNewValue); //by default, source value type is deducted from target member type to allow //memberless binding, if targetMember exists, it will be used to determine target //value type for conversion CompilerServices.emitConvert (il, piSource.PropertyType); il.Emit (OpCodes.Callvirt, piSource.GetSetMethod ()); il.MarkLabel (endMethod); il.Emit (OpCodes.Ret); //vc dyn meth is stored in a cached list, it will be bound to datasource only //when datasource of source graphic object changed dmVC = dsValueChangedDynMeths.Count; dsValueChangedDynMeths.Add (dm); #endregion } #region emit dataSourceChanged event handler //now we create the datasource changed method that will init the destination member with //the actual value of the origin member of the datasource and then will bind the value changed //dyn methode. //dm is bound to the instanciator instance to have access to cached dyn meth and delegates dm = new DynamicMethod ("dyn_dschanged", typeof (void), CompilerServices.argsBoundDSChange, true); il = dm.GetILGenerator (256); il.DeclareLocal (CompilerServices.TObject);//used for checking propery less bindings il.DeclareLocal (typeof(MemberInfo));//used for checking propery less bindings System.Reflection.Emit.Label cancel = il.DefineLabel (); System.Reflection.Emit.Label cancelInit = il.DefineLabel (); il.Emit (OpCodes.Nop); emitRemoveOldDataSourceHandler(il, "ValueChanged", delName); if (!string.IsNullOrEmpty(bindingDef.TargetMember)){ if (bindingDef.TwoWay){ System.Reflection.Emit.Label cancelRemove = il.DefineLabel (); //remove handler if not null il.Emit (OpCodes.Ldarg_2);//load old parent il.Emit (OpCodes.Ldfld, CompilerServices.fiDSCOldDS); il.Emit (OpCodes.Brfalse, cancelRemove);//old parent is null //remove handler il.Emit (OpCodes.Ldarg_2);//1st arg load old datasource il.Emit (OpCodes.Ldfld, CompilerServices.fiDSCOldDS); il.Emit (OpCodes.Ldstr, "ValueChanged");//2nd arg event name il.Emit (OpCodes.Ldarg_1);//3d arg: instance bound to delegate (the source) il.Emit (OpCodes.Call, CompilerServices.miRemEvtHdlByTarget); il.MarkLabel(cancelRemove); } il.Emit (OpCodes.Ldarg_2);//load datasource change arg il.Emit (OpCodes.Ldfld, CompilerServices.fiDSCNewDS); il.Emit (OpCodes.Brfalse, cancel);//new ds is null } #region fetch initial Value if (!string.IsNullOrEmpty(bindingDef.TargetMember)){ il.Emit (OpCodes.Ldarg_2);//load new datasource il.Emit (OpCodes.Ldfld, CompilerServices.fiDSCNewDS); il.Emit (OpCodes.Ldstr, bindingDef.TargetMember);//load member name il.Emit (OpCodes.Call, CompilerServices.miGetMembIinfoWithRefx); il.Emit (OpCodes.Stloc_1);//save memberInfo il.Emit (OpCodes.Ldloc_1);//push mi for test if null il.Emit (OpCodes.Brfalse, cancelInit);//propertyLessBinding } il.Emit (OpCodes.Ldarg_1);//load source of dataSourceChanged which is the dest instance il.Emit (OpCodes.Ldarg_2);//load new datasource il.Emit (OpCodes.Ldfld, CompilerServices.fiDSCNewDS); if (!string.IsNullOrEmpty(bindingDef.TargetMember)){ il.Emit (OpCodes.Ldloc_1);//push mi for value fetching il.Emit (OpCodes.Call, CompilerServices.miGetValWithRefx); } CompilerServices.emitConvert (il, piSource.PropertyType); il.Emit (OpCodes.Callvirt, piSource.GetSetMethod ()); #endregion if (!string.IsNullOrEmpty(bindingDef.TargetMember)){ il.MarkLabel(cancelInit); //check if new dataSource implement IValueChange il.Emit (OpCodes.Ldarg_2);//load new datasource il.Emit (OpCodes.Ldfld, CompilerServices.fiDSCNewDS); il.Emit (OpCodes.Isinst, typeof(IValueChange)); il.Emit (OpCodes.Brfalse, cancel); il.Emit(OpCodes.Ldarg_0);//load ref to this instanciator onto the stack il.Emit (OpCodes.Ldarg_1);//load datasource change source il.Emit (OpCodes.Ldarg_2);//load new datasource il.Emit (OpCodes.Ldfld, CompilerServices.fiDSCNewDS); il.Emit(OpCodes.Ldc_I4, dmVC);//load index of dynmathod il.Emit (OpCodes.Call, CompilerServices.miDSChangeEmitHelper); if (bindingDef.TwoWay){ il.Emit (OpCodes.Ldarg_1);//arg1: dataSourceChange source, the origine of the binding il.Emit (OpCodes.Ldstr, bindingDef.SourceMember);//arg2: orig member il.Emit (OpCodes.Ldarg_2);//arg3: new datasource il.Emit (OpCodes.Ldfld, CompilerServices.fiDSCNewDS); il.Emit (OpCodes.Ldstr, bindingDef.TargetMember);//arg4: dest member il.Emit (OpCodes.Call, CompilerServices.miDSReverseBinding); } il.MarkLabel (cancel); } 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)); #endregion ctx.emitCachedDelegateHandlerAddition(delDSIndex, CompilerServices.eiDSChange); }