/// <summary>
        /// Converts source values to a value for the binding target.
        /// </summary>
        /// <param name="values">The array of values that the source bindings produces.</param>
        /// <param name="targetType">The type of the binding target property.</param>
        /// <param name="parameter">The converter parameter to use.</param>
        /// <param name="culture">The culture to use in the converter.</param>
        /// <returns>A converted value.</returns>
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            try
            {
                // First time around we parse the evaluation input
                if (_eval == null)
                {
                    _eval = new Eval(_language);
                    _eval.ResolveIdentifier += new EventHandler <ResolveIdentifierEventArgs>(OnResolveIdentifier);
                    _eval.Parse(_expression);
                }

                // Every time we evaluate we could throw an exception. This is because each time around the
                // bindings can provide values of different types. So first time round the binding has an
                // integer and so works correctly but next time it could provide a string and cause a type
                // error in the evaluation.
                EvalResult ret = _eval.Evaluate(values);

                // Null means we have no result to provide
                if (ret == null)
                {
                    return(DependencyProperty.UnsetValue);
                }
                else
                {
                    // If the return type is different to the target type
                    if (ret.Value.GetType() != targetType)
                    {
                        // If possible we perform an implicit conversion to the target
                        TypeCode targetTypeCode = Type.GetTypeCode(targetType);
                        if (ImplicitConverter.CanConvertTo(targetTypeCode, ret.Value, _language))
                        {
                            ret.Value = ImplicitConverter.ConvertTo(targetTypeCode, ret.Value, _language);
                        }
                        else
                        {
                            // Use type converters to attempt an explicit conversion
                            ret.Value = ConvertUsingConverter(ret, targetType);
                        }
                    }

                    return(ret.Value);
                }
            }
            catch (ParseException pe)
            {
                Console.WriteLine("EvalBinding Parsing Exception : {0} : Index '{1}'", pe.Message, pe.Index);
                return(DependencyProperty.UnsetValue);
            }
            catch (Exception e)
            {
                Console.WriteLine("EvalBinding Evaluation Exception : {0} : Eval '{1}'", e.Message, _eval.ToString());
                return(DependencyProperty.UnsetValue);
            }
        }
Beispiel #2
0
        private EvalResult EvaluateMethod(MethodInfo[] mis, object target, EvalResult[] args)
        {
            if (mis == null)
            {
                if (target == null)
                {
                    throw new ApplicationException("Cannot find static public method called '" + Identifier + "'.");
                }
                else
                {
                    throw new ApplicationException("Cannot find instance public method called '" + Identifier + "'.");
                }
            }

            MethodInfo callMi = null;

            object[] callParams = null;

            // Find methods that we could call
            foreach (MethodInfo mi in mis)
            {
                // Matching name?
                if (mi.Name == Identifier)
                {
                    ParameterInfo[] pis = mi.GetParameters();

                    // Is the last parameter an array of params?
                    bool paramArray = (pis.Length > 0 ? pis[pis.Length - 1].IsDefined(typeof(ParamArrayAttribute), false) : false);

                    // It must have the same number of parameters as we have arguments
                    if (!paramArray && (pis.Length == args.Length))
                    {
                        // Match parameter types?
                        int      i         = 0;
                        int      exact     = 0;
                        object[] pisParams = new object[args.Length];
                        for (i = 0; i < pis.Length; i++)
                        {
                            TypeCode methodTc = Type.GetTypeCode(pis[i].ParameterType);

                            // Note how many parameters are an exact match
                            if (methodTc == args[i].Type)
                            {
                                pisParams[i] = args[i].Value;
                                exact++;
                            }
                            else
                            {
                                // If cannot be implicitly converted, then fail to match at all
                                if (ImplicitConverter.CanConvertTo(methodTc, args[i].Value, _language))
                                {
                                    pisParams[i] = ImplicitConverter.ConvertTo(methodTc, args[i].Value, _language);
                                }
                                else
                                {
                                    break;
                                }
                            }
                        }

                        // If all parameters exactly match
                        if (exact == pis.Length)
                        {
                            // Use this method
                            callMi     = mi;
                            callParams = pisParams;
                            break;
                        }

                        // Remember the first compatible match we find
                        if ((i == pis.Length) && (callMi == null))
                        {
                            callMi     = mi;
                            callParams = pisParams;
                        }
                    }
                    else if (paramArray)
                    {
                        // We can only handle packaging up a param array as an object array
                        int lastIndex = pis.Length - 1;
                        if (pis[lastIndex].ParameterType == typeof(object[]))
                        {
                            // Package up the extra parameters into an object array
                            object[] pisParams  = new object[pis.Length];
                            object[] lastParams = new object[args.Length - lastIndex];
                            pisParams[lastIndex] = lastParams;
                            for (int j = 0; j < lastParams.Length; j++)
                            {
                                lastParams[j] = args[j + lastIndex].Value;
                            }

                            // Match parameter types for all but the last 'object[]' entry?
                            int i     = 0;
                            int exact = 0;
                            for (i = 0; i < lastIndex; i++)
                            {
                                TypeCode methodTc = Type.GetTypeCode(pis[i].ParameterType);

                                // Note how many parameters are an exact match
                                if (methodTc == args[i].Type)
                                {
                                    pisParams[i] = args[i].Value;
                                    exact++;
                                }
                                else
                                {
                                    // If cannot be implicitly converted, then fail to match at all
                                    if (ImplicitConverter.CanConvertTo(methodTc, args[i].Value, _language))
                                    {
                                        pisParams[i] = ImplicitConverter.ConvertTo(methodTc, args[i].Value, _language);
                                    }
                                    else
                                    {
                                        break;
                                    }
                                }
                            }

                            // If all parameters exactly match
                            if (exact == lastIndex)
                            {
                                // Use this method
                                callMi     = mi;
                                callParams = pisParams;
                                break;
                            }

                            // Remember the first compatible match we find
                            if ((i == lastIndex) && (callMi == null))
                            {
                                callMi     = mi;
                                callParams = pisParams;
                            }
                        }
                    }
                }
            }

            if (callMi == null)
            {
                if (target == null)
                {
                    throw new ApplicationException("Cannot find static public method called '" + Identifier + "' with matching parameters to those provided.");
                }
                else
                {
                    throw new ApplicationException("Cannot find instance public method called '" + Identifier + "' with matching parameters to those provided.");
                }
            }

            // Call the static method and return result
            EvalResult ret = new EvalResult();

            ret.Value = callMi.Invoke(target, callParams);
            return(DiscoverTypeCode(ret));
        }
        private EvalResult EvaluateObjectInstance(EvalResult target,
                                                  EvalResult[] args,
                                                  object thisObject)
        {
            // Get the type definition of the target instance
            Type t = target.Value.GetType();

            // Get the list of all properties that might be of interest to us
            PropertyInfo[] pis = t.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty);

            PropertyInfo callPi = null;

            object[] callParams = null;

            // Find properties that we could call
            foreach (PropertyInfo pi in pis)
            {
                // Object indexers are compiled from 'this[...]' in C# to the fixed name 'Item'
                if (pi.Name == "Item")
                {
                    // Grab the list of parameters for this property accessor
                    ParameterInfo[] infos = pi.GetIndexParameters();

                    // Is the last parameter an array of params?
                    bool paramArray = (infos.Length > 0 ? infos[infos.Length - 1].IsDefined(typeof(ParamArrayAttribute), false) : false);

                    // It must have the same number of parameters as we have arguments
                    if (!paramArray && (infos.Length == args.Length))
                    {
                        // Match parameter types?
                        int      i          = 0;
                        int      exact      = 0;
                        object[] infoParams = new object[args.Length];
                        for (i = 0; i < infos.Length; i++)
                        {
                            TypeCode paramTc = Type.GetTypeCode(infos[i].ParameterType);

                            // Note how many parameters are an exact match
                            if (paramTc == args[i].Type)
                            {
                                infoParams[i] = args[i].Value;
                                exact++;
                            }
                            else
                            {
                                // If cannot be implicitly converted, then fail to match at all
                                if (ImplicitConverter.CanConvertTo(paramTc, args[i].Value, _language))
                                {
                                    infoParams[i] = ImplicitConverter.ConvertTo(paramTc, args[i].Value, _language);
                                }
                                else
                                {
                                    break;
                                }
                            }
                        }

                        // If all parameters exactly match
                        if (exact == infos.Length)
                        {
                            // Use this method
                            callPi     = pi;
                            callParams = infoParams;
                            break;
                        }

                        // Remember the first compatible match we find
                        if ((i == infos.Length) && (callPi == null))
                        {
                            callPi     = pi;
                            callParams = infoParams;
                        }
                    }
                    else if (paramArray)
                    {
                        // We can only handle packaging up a param array as an object array
                        int lastIndex = infos.Length - 1;
                        if (infos[lastIndex].ParameterType == typeof(object[]))
                        {
                            // Package up the extra parameters into an object array
                            object[] infoParams = new object[infos.Length];
                            object[] lastParams = new object[args.Length - lastIndex];
                            infoParams[lastIndex] = lastParams;
                            for (int j = 0; j < lastParams.Length; j++)
                            {
                                lastParams[j] = args[j + lastIndex].Value;
                            }

                            // Match parameter types for all but the last 'object[]' entry?
                            int i     = 0;
                            int exact = 0;
                            for (i = 0; i < lastIndex; i++)
                            {
                                TypeCode paramTc = Type.GetTypeCode(infos[i].ParameterType);

                                // Note how many parameters are an exact match
                                if (paramTc == args[i].Type)
                                {
                                    infoParams[i] = args[i].Value;
                                    exact++;
                                }
                                else
                                {
                                    // If cannot be implicitly converted, then fail to match at all
                                    if (ImplicitConverter.CanConvertTo(paramTc, args[i].Value, _language))
                                    {
                                        infoParams[i] = ImplicitConverter.ConvertTo(paramTc, args[i].Value, _language);
                                    }
                                    else
                                    {
                                        break;
                                    }
                                }
                            }

                            // If all parameters exactly match
                            if (exact == lastIndex)
                            {
                                // Use this method
                                callPi     = pi;
                                callParams = infoParams;
                                break;
                            }

                            // Remember the first compatible match we find
                            if ((i == lastIndex) && (callPi == null))
                            {
                                callPi     = pi;
                                callParams = infoParams;
                            }
                        }
                    }
                }
            }

            if (callPi == null)
            {
                throw new ApplicationException("Cannot find array acessor for type '" + target.Type.ToString() + "' with matching number and type of arguments.");
            }

            // Call the static method and return result
            EvalResult ret = new EvalResult();

            ret.Value = callPi.GetValue(target.Value, callParams);
            return(DiscoverTypeCode(ret));
        }