private Tuple <string, Delegate, string[], DataContainer[]> GetLambda(string expression) { Tuple <string, Delegate, string[], DataContainer[]> tuple; if (handlers.TryGetValue(expression, out tuple)) { return(tuple); } List <ParameterExpression> parameters; List <DataContainer> dataContainers; Expression exp = EquationTokenizer.Tokenize(expression, false).GetExpression(out parameters, out dataContainers, DynamicContext, false); Delegate del = Expression.Lambda(exp, parameters.ToArray()).Compile(); tuple = new Tuple <string, Delegate, string[], DataContainer[]>(exp.ToString(), del, parameters.Select(p => p.Name).ToArray(), dataContainers.ToArray()); handlers.Add(expression, tuple); return(tuple); }
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) { for (int i = 0; i < values.Length; ++i) { if (values[i] == DependencyProperty.UnsetValue || _namedObjectType.IsInstanceOfType(values[i]) || (PTypes[i] != null && !PTypes[i].IsInstanceOfType(values[i]))) { return(DependencyProperty.UnsetValue); } } object result; try { result = _converter(values, _values); } catch (Exception e) { LastException = e; ++ExceptionCount; if (Debugger.IsAttached) { Console.WriteLine("QuickMultiConverter Exception (\"" + ConvertExpression + "\") - " + e.Message + (e.InnerException != null ? " (Inner - " + e.InnerException.Message + ")" : "")); } EquationTokenizer.ThrowQuickConverterEvent(new RuntimeMultiConvertExceptionEventArgs(ConvertExpression, ConvertExpressionDebugView, values, pIndices, null, _values, parameter, this, e)); return(DependencyProperty.UnsetValue); } finally { if (_toDataContainers != null) { foreach (var container in _toDataContainers) { container.Value = null; } } } result = CastResult(result, targetType); return(result); }
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) { object[] ret = new object[_convertBack.Length]; if (ValueType != null && !ValueType.IsInstanceOfType(value)) { for (int i = 0; i < ret.Length; ++i) { ret[i] = System.Windows.Data.Binding.DoNothing; } return(ret); } for (int i = 0; i < _convertBack.Length; ++i) { try { ret[i] = _convertBack[i](value, _values); } catch (Exception e) { LastException = e; ++ExceptionCount; if (Debugger.IsAttached) { Console.WriteLine("QuickMultiConverter Exception (\"" + ConvertBackExpression[i] + "\") - " + e.Message + (e.InnerException != null ? " (Inner - " + e.InnerException.Message + ")" : "")); } EquationTokenizer.ThrowQuickConverterEvent(new RuntimeMultiConvertExceptionEventArgs(ConvertBackExpression[i], ConvertBackExpressionDebugView[i], null, pIndices, value, _values, parameter, this, e)); ret[i] = DependencyProperty.UnsetValue; } ret[i] = CastResult(ret[i], targetTypes[i]); } if (_fromDataContainers != null) { foreach (var container in _fromDataContainers) { container.Value = null; } } return(ret); }
private Tuple <string, Delegate, ParameterExpression[], DataContainer[]> GetLambda(string expression, bool convertBack) { List <ParameterExpression> parameters; List <DataContainer> dataContainers; Expression exp = EquationTokenizer.Tokenize(expression).GetExpression(out parameters, out dataContainers, DynamicContext); ParameterExpression invalid; if (convertBack) { invalid = parameters.FirstOrDefault(par => par.Name != "value" && (par.Name.Length != 2 || par.Name[0] != 'V' || !Char.IsDigit(par.Name[1]))); } else { invalid = parameters.FirstOrDefault(par => par.Name.Length != 2 || (par.Name[0] != 'P' && par.Name[0] != 'V') || !Char.IsDigit(par.Name[1])); } if (invalid != null) { throw new Exception("\"$" + invalid.Name + "\" is not a valid parameter name for conversion " + (convertBack ? "to" : "from") + " source."); } Delegate del = Expression.Lambda(Expression.Convert(exp, typeof(object)), parameters.ToArray()).Compile(); return(new Tuple <string, Delegate, ParameterExpression[], DataContainer[]>(exp.ToString(), del, parameters.ToArray(), dataContainers.ToArray())); }
public override object ProvideValue(IServiceProvider serviceProvider) { try { Tuple <string, Func <object[], object[], object>, string[], DataContainer[]> func = null; if (Converter != null && !toFunctions.TryGetValue(Converter, out func)) { Tuple <string, Delegate, ParameterExpression[], DataContainer[]> tuple = GetLambda(Converter, false); if (tuple == null) { return(null); } List <string> parNames = new List <string>(); int pCount = 0; ParameterExpression inputP = Expression.Parameter(typeof(object[])); ParameterExpression inputV = Expression.Parameter(typeof(object[])); int[] inds = new int[10]; foreach (var par in tuple.Item3.Where(p => p.Name[0] == 'P').OrderBy(e => e.Name)) { parNames.Add(par.Name); inds[par.Name[1] - '0'] = pCount++; } var arguments = tuple.Item3.Select <ParameterExpression, Expression>(par => { if (par.Name[0] == 'P') { return(Expression.ArrayIndex(inputP, Expression.Constant(inds[par.Name[1] - '0']))); } return(Expression.ArrayIndex(inputV, Expression.Constant((int)(par.Name[1] - '0')))); }); Expression exp = Expression.Call(Expression.Constant(tuple.Item2, tuple.Item2.GetType()), tuple.Item2.GetType().GetMethod("Invoke"), arguments); var result = Expression.Lambda <Func <object[], object[], object> >(exp, inputP, inputV).Compile(); func = new Tuple <string, Func <object[], object[], object>, string[], DataContainer[]>(tuple.Item1, result, parNames.ToArray(), tuple.Item4); toFunctions.Add(Converter, func); } Tuple <string, Func <object, object[], object>, DataContainer[]>[] backFuncs = new Tuple <string, Func <object, object[], object>, DataContainer[]> [10]; for (int i = 0; i <= 9; ++i) { var converter = typeof(QuickMultiConverter).GetProperty("ConvertBack" + i).GetValue(this, null) as string; if (String.IsNullOrWhiteSpace(converter)) { backFuncs[i] = new Tuple <string, Func <object, object[], object>, DataContainer[]>(null, null, new DataContainer[0]); continue; } Tuple <string, Delegate, ParameterExpression[], DataContainer[]> tuple = GetLambda(converter, true); if (tuple == null) { backFuncs[i] = new Tuple <string, Func <object, object[], object>, DataContainer[]>(null, null, new DataContainer[0]); continue; } ParameterExpression val = Expression.Parameter(typeof(object)); ParameterExpression inV = Expression.Parameter(typeof(object[])); var arguments = tuple.Item3.Select <ParameterExpression, Expression>(par => { if (par.Name[0] == 'V') { return(Expression.ArrayIndex(inV, Expression.Constant((int)(par.Name[1] - '0')))); } return(val); }); Expression exp = Expression.Call(Expression.Constant(tuple.Item2, tuple.Item2.GetType()), tuple.Item2.GetType().GetMethod("Invoke"), arguments); var result = Expression.Lambda <Func <object, object[], object> >(exp, val, inV).Compile(); backFuncs[i] = new Tuple <string, Func <object, object[], object>, DataContainer[]>(tuple.Item1, result, tuple.Item4); } if (func == null) { func = new Tuple <string, Func <object[], object[], object>, string[], DataContainer[]>(null, null, null, null); } List <object> pTypes = new List <object>(); List <int> pIndicies = new List <int>(); List <Tuple <string, Func <object, object[], object>, DataContainer[], string> > backs = new List <Tuple <string, Func <object, object[], object>, DataContainer[], string> >(); if (func.Item3 != null) { foreach (string name in func.Item3) { int index = name[1] - '0'; pIndicies.Add(index); pTypes.Add(typeof(QuickMultiConverter).GetProperty(name + "Type").GetValue(this, null)); backs.Add(new Tuple <string, Func <object, object[], object>, DataContainer[], string>(backFuncs[index].Item1, backFuncs[index].Item2, backFuncs[index].Item3, typeof(QuickMultiConverter).GetProperty("ConvertBack" + name[1]).GetValue(this, null) as string)); } } List <object> vals = new List <object>(); for (int i = 0; i <= 9; ++i) { vals.Add(typeof(QuickMultiConverter).GetProperty("V" + i).GetValue(this, null)); } _parameterOrder = func.Item3; return(new DynamicMultiConverter(func.Item2, backs.Select(t => t.Item2).ToArray(), vals.ToArray(), Converter, func.Item1, backs.Select(t => t.Item4).ToArray(), backs.Select(t => t.Item1).ToArray(), pTypes.Select(t => QuickConverter.GetType(t)).ToArray(), pIndicies.ToArray(), QuickConverter.GetType(ValueType), func.Item4, backs.SelectMany(t => t.Item3).ToArray(), ChainedConverter)); } catch (Exception e) { EquationTokenizer.ThrowQuickConverterEvent(new MarkupExtensionExceptionEventArgs(Converter, this, e)); throw; } }
public override object ProvideValue(IServiceProvider serviceProvider) { try { if (P == null) { return(null); } bool getExpression; if (serviceProvider == null) { getExpression = false; } else { var targetProvider = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget; if (targetProvider != null && (targetProvider.TargetObject is Setter)) { getExpression = false; } else if (targetProvider == null || !(targetProvider.TargetProperty is PropertyInfo)) { getExpression = true; } else { Type propType = (targetProvider.TargetProperty as PropertyInfo).PropertyType; if (propType == typeof(Binding)) { return(this); } getExpression = !propType.IsAssignableFrom(typeof(System.Windows.Data.MultiBinding)); } } P.Converter = new QuickConverter() { Convert = Convert, ConvertBack = ConvertBack, DynamicContext = DynamicContext, PType = PType, V0 = V0, V1 = V1, V2 = V2, V3 = V3, V4 = V4, V5 = V5, V6 = V6, V7 = V7, V8 = V8, V9 = V9 }.Get(); return(getExpression ? P.ProvideValue(serviceProvider) : P); } catch (Exception e) { EquationTokenizer.ThrowQuickConverterEvent(new MarkupExtensionExceptionEventArgs(Convert, this, e)); throw; } }
public override object ProvideValue(IServiceProvider serviceProvider) { try { bool getExpression; if (serviceProvider == null) { getExpression = false; } else { var targetProvider = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget; if (targetProvider != null && (targetProvider.TargetObject is Setter)) { getExpression = false; } else if (targetProvider == null || !(targetProvider.TargetProperty is PropertyInfo)) { getExpression = true; } else { Type propType = (targetProvider.TargetProperty as PropertyInfo).PropertyType; if (propType == typeof(MultiBinding)) { return(this); } getExpression = !propType.IsAssignableFrom(typeof(System.Windows.Data.MultiBinding)); } } var holder = new System.Windows.Data.MultiBinding() { Mode = Mode, UpdateSourceTrigger = UpdateSourceTrigger }; if (FallbackValue != null) { holder.FallbackValue = FallbackValue; } if (TargetNullValue != null) { holder.TargetNullValue = TargetNullValue; } if (ExternalConverter == null) { holder.ConverterParameter = ConverterParameter; string[] parameterOrder; holder.Converter = new QuickMultiConverter() { Converter = Converter, DynamicContext = DynamicContext, P0Type = P0Type, P1Type = P1Type, P2Type = P2Type, P3Type = P3Type, P4Type = P4Type, P5Type = P5Type, P6Type = P6Type, P7Type = P7Type, P8Type = P8Type, P9Type = P9Type, V0 = V0, V1 = V1, V2 = V2, V3 = V3, V4 = V4, V5 = V5, V6 = V6, V7 = V7, V8 = V8, V9 = V9, ConvertBack0 = ConvertBack0, ConvertBack1 = ConvertBack1, ConvertBack2 = ConvertBack2, ConvertBack3 = ConvertBack3, ConvertBack4 = ConvertBack4, ConvertBack5 = ConvertBack5, ConvertBack6 = ConvertBack6, ConvertBack7 = ConvertBack7, ConvertBack8 = ConvertBack8, ConvertBack9 = ConvertBack9 }.Get(out parameterOrder); foreach (string name in parameterOrder) { holder.Bindings.Add(typeof(MultiBinding).GetProperty(name).GetValue(this, null) as BindingBase); } if (!_modeSet) { bool exists = false; for (int i = 0; i <= 9; ++i) { exists |= !String.IsNullOrWhiteSpace(typeof(MultiBinding).GetProperty("ConvertBack" + i).GetValue(this, null) as string); } holder.Mode = exists ? BindingMode.TwoWay : BindingMode.OneWay; } } else { if (ExternalConverterParameterMode == ConverterParameterMode.Parameter) { holder.ConverterParameter = ConverterParameter; } else { holder.ConverterParameter = new object[] { V0, V1, V2, V3, V4, V5, V6, V7, V8, V9 } }; holder.Converter = ExternalConverter; for (int i = 0; i <= 9; ++i) { var binding = typeof(MultiBinding).GetProperty("P" + i).GetValue(this, null) as BindingBase; if (binding != null) { holder.Bindings.Add(binding); } } } return(getExpression ? holder.ProvideValue(serviceProvider) : holder); } catch (Exception e) { EquationTokenizer.ThrowQuickConverterEvent(new MarkupExtensionExceptionEventArgs(Converter, this, e)); throw; } }
private object DoConversion(object value, Type targetType, object parameter, Func <object, object[], object, object> func, bool convertingBack, CultureInfo culture) { if (convertingBack) { if (_chainedConverter != null) { try { value = _chainedConverter.ConvertBack(value, targetType, parameter, culture); } catch (Exception e) { EquationTokenizer.ThrowQuickConverterEvent(new ChainedConverterExceptionEventArgs(ConvertExpression, value, targetType, parameter, culture, true, _chainedConverter, this, e)); return(DependencyProperty.UnsetValue); } if (value == DependencyProperty.UnsetValue || value == System.Windows.Data.Binding.DoNothing) { return(value); } } if (ValueType != null && !ValueType.IsInstanceOfType(value)) { return(System.Windows.Data.Binding.DoNothing); } } else { if (value == DependencyProperty.UnsetValue || _namedObjectType.IsInstanceOfType(value) || (PType != null && !PType.IsInstanceOfType(value))) { return(DependencyProperty.UnsetValue); } } object result = value; if (func != null) { try { result = func(result, _values, parameter); } catch (Exception e) { LastException = e; ++ExceptionCount; if (Debugger.IsAttached) { Console.WriteLine("QuickMultiConverter Exception (\"" + (convertingBack ? ConvertBackExpression : ConvertExpression) + "\") - " + e.Message + (e.InnerException != null ? " (Inner - " + e.InnerException.Message + ")" : "")); } if (convertingBack) { EquationTokenizer.ThrowQuickConverterEvent(new RuntimeSingleConvertExceptionEventArgs(ConvertBackExpression, ConvertBackExpressionDebugView, null, value, _values, parameter, this, e)); } else { EquationTokenizer.ThrowQuickConverterEvent(new RuntimeSingleConvertExceptionEventArgs(ConvertExpression, ConvertExpressionDebugView, value, null, _values, parameter, this, e)); } return(DependencyProperty.UnsetValue); } finally { var dataContainers = convertingBack ? _fromDataContainers : _toDataContainers; if (dataContainers != null) { foreach (var container in dataContainers) { container.Value = null; } } } } if (result == DependencyProperty.UnsetValue || result == System.Windows.Data.Binding.DoNothing) { return(result); } if (!convertingBack && _chainedConverter != null) { try { result = _chainedConverter.Convert(result, targetType, parameter, culture); } catch (Exception e) { EquationTokenizer.ThrowQuickConverterEvent(new ChainedConverterExceptionEventArgs(ConvertExpression, result, targetType, parameter, culture, false, _chainedConverter, this, e)); return(DependencyProperty.UnsetValue); } } if (result == DependencyProperty.UnsetValue || result == System.Windows.Data.Binding.DoNothing || result == null || targetType == null || targetType == typeof(object)) { return(result); } if (targetType == typeof(string)) { return(result.ToString()); } Func <object, object> cast; if (!castFunctions.TryGetValue(targetType, out cast)) { ParameterExpression par = Expression.Parameter(typeof(object)); cast = Expression.Lambda <Func <object, object> >(Expression.Convert(Expression.Dynamic(Binder.Convert(CSharpBinderFlags.ConvertExplicit, targetType, typeof(object)), targetType, par), typeof(object)), par).Compile(); castFunctions.TryAdd(targetType, cast); } if (cast != null) { try { result = cast(result); } catch { castFunctions[targetType] = null; } } return(result); }