Пример #1
0
        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);
        }
Пример #2
0
 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);
     }
 }
Пример #3
0
        /// <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);
        }
Пример #4
0
 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);
 }
Пример #5
0
        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);
        }
Пример #6
0
        /// <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;
        }
Пример #7
0
        /// <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);
        }