internal DataSetValue(ValueDescriptor descriptor, object value) { Debug.Assert(descriptor != null); Descriptor = descriptor; Value = value; }
private static IEnumerable <double> ToNumbers(ValueDescriptor descriptor, CultureInfo culture, IEnumerable <object> values) { return(values .Select(x => ValueConversions.ToNumber(descriptor, culture, x)) .Where(x => x.HasValue) .Select(x => x.Value)); }
/// <summary> /// Infrastructure. Converts a value into the proper type required by a <see cref="ValueDescriptor"/> /// and then to its representation as <see cref="double"/> number. /// </summary> /// <param name="descriptor">Descriptor for which the object to convert represents the value.</param> /// <param name="culture">Culture used to perform conversion, if required.</param> /// <param name="value"> /// Value to convert to the exact type required by <paramref name="descriptor"/> and then to /// its numeric representation. /// </param> /// <returns> /// The numeric representation of <paramref name="value"/> after it has been converted to the /// type required by <paramref name="descriptor"/>. If type cannot be converted to a number (for example because /// required type is a string) then it returns <see langword="null"/>. /// </returns> /// <exception cref="FormatException"> /// <paramref name="value"/> cannot be converted to the type required by <paramref name="descriptor"/> /// using the specified culture. /// </exception> /// <exception cref="InvalidCastException"> /// <paramref name="value"/> cannot be converted to the type required by <paramref name="descriptor"/> /// using the specified culture. /// <br/>-or-<br/> /// <paramref name="value"/> is a <see cref="bool"/> and required type is a <see cref="double"/>. This /// conversion is possible but it's probably unwanted then it's not allowed implictly. /// </exception> /// <exception cref="OverflowException"> /// <paramref name="value"/> cannot be converted to the type required by <paramref name="descriptor"/> /// because it's too big or to small to be represented as a <see cref="double"/> value. /// </exception> public static double?ToNumber(ValueDescriptor descriptor, CultureInfo culture, object value) { Debug.Assert(descriptor != null); Debug.Assert(culture != null); if (descriptor.Type == TypeOfValue.String) { return(null); } if (descriptor.Type == TypeOfValue.Boolean) { return(ToBoolean(culture, value) ? 1 : 0); } if (value is bool) { throw new InvalidCastException("Required type is System.Double, cannot automatically convert from System.Boolean values."); } // Null for doubles are simply ignored, it's not safe to assume 0 here if (value == null) { return(null); } return((double)Convert.ChangeType(value, typeof(double), culture)); }
public static IEnumerable <object> Project(ValueDescriptor descriptor, CultureInfo culture, IEnumerable <object> values, NCalc.Expression expression) { return(values.Select(x => { expression.Parameters[ExpressionEvaluator.IdentifierValue] = x; return expression.Evaluate(); })); }
public object Evaluate(ValueDescriptor descriptor, string expression) { Debug.Assert(descriptor != null); _descriptor = new Lazy <ValueDescriptor>(() => descriptor); _currentExpression = CreateExpression(expression); return(_currentExpression.Evaluate()); }
internal DataError(IssueSeverity severity, ValueDescriptor item, string message) { Debug.Assert(!String.IsNullOrWhiteSpace(message)); Severity = severity; Item = item; Message = message; }
public static object Average(ValueDescriptor descriptor, CultureInfo culture, IEnumerable <object> values) { var numbers = ToNumbers(descriptor, culture, values); if (numbers.Any()) { return(numbers.Sum() / numbers.Count()); } return(null); }
private IEnumerable <object> Filter(ValueDescriptor descriptor, IEnumerable <object> values) { Debug.Assert(descriptor != null); Debug.Assert(values != null); if (descriptor.PreferredAggregation == AggregationMode.Count && Options.HasFlag(AggregationOptions.ExcludeNullValuesFromCount)) { return(values.Where(x => x != null)); } return(values); }
public IEnumerable <object> this[ValueDescriptor descriptor] { get { Debug.Assert(descriptor != null); Debug.Assert(_items != null); List <object> values; if (_items.TryGetValue(descriptor, out values)) { return(values); } return(Enumerable.Empty <object>()); } }
/// <summary> /// Adds a new value to this dataset associated with the specified <see cref="ValueDescriptor"/>. /// </summary> /// <param name="descriptor">Reference ID for the descriptor of this value.</param> /// <param name="value"> /// Value to add to the dataset, when required it will be converted to the proper data type mandated /// by its descriptor (eventually using <see cref="Culture"/> for the conversion). /// </param> /// <returns>The newly added value.</returns> /// <exception cref="ArgumentNullException"> /// If <paramref name="descriptor"/> is <see langword="null"/>. /// </exception> /// <exception cref="ArgumentException"> /// If <paramref name="descriptor"/> does not belong to <see cref="Protocol"/>. /// </exception> public DataSetValue AddValue(ValueDescriptor descriptor, object value) { Debug.Assert(_cachedDescriptorsLookUp != null); if (descriptor == null) { throw new ArgumentNullException(nameof(descriptor)); } if (!_cachedDescriptorsLookUp.ContainsKey(descriptor.Reference)) { throw new ArgumentException("Specified descriptor does not belong to the protocol associated with this object.", nameof(descriptor)); } return(AddValueCore(descriptor, value)); }
private DataSetValue AddValueCore(ValueDescriptor descriptor, object value) { Debug.Assert(Values != null); Debug.Assert(descriptor != null && !String.IsNullOrWhiteSpace(descriptor.Reference)); // TryGetValue() approach is faster but it's easier to keep DataSetValue immutable // because we do not need to track external changes and we just use IsChangedAfterLastCalculation. Values.Remove(descriptor.Reference); var item = new DataSetValue(descriptor, value); Values.Add(descriptor.Reference, item); IsChangedAfterLastCalculation = true; return(item); }
private bool IsEnabled(ValueDescriptor descriptor) { Debug.Assert(descriptor != null); if (String.IsNullOrWhiteSpace(descriptor.EnabledIfExpression)) { return(true); } bool enabled; if (_evaluator.Evaluate(() => descriptor.EnabledIfExpression, out enabled)) { return(enabled); } return(false); }
private object Aggregate(DataSet dataset, ValueDescriptor descriptor, IEnumerable <object> values) { Debug.Assert(descriptor != null); Debug.Assert(values != null); Debug.Assert(_accumulator.IsEmpty || _culture != null); if (!String.IsNullOrWhiteSpace(descriptor.AggregationExpression)) { var evaluator = new ExpressionEvaluator(dataset); evaluator.AddConstant(ExpressionEvaluator.IdentifierValues, values); return(evaluator.Evaluate(() => descriptor.AggregationExpression)); } // TODO: AggregationMode.None may be checked at the very beginning, no need to create a // list of values if there is nothing to do with them... if (descriptor.PreferredAggregation == AggregationMode.None) { return(null); } if (descriptor.PreferredAggregation == AggregationMode.Count) { return(values.Count()); } var numbers = values .Select(x => ValueConversions.ToNumber(descriptor, _culture, x)) .Where(x => x.HasValue); // Sum of an empty set is zero but average is null if (descriptor.PreferredAggregation == AggregationMode.Sum) { return(numbers.Sum()); } if (descriptor.PreferredAggregation == AggregationMode.Average) { return(numbers.Any() ? (object)(numbers.Sum() / numbers.Count()) : null); } throw new NotSupportedException(); }
private object Transform(DataSet dataset, ValueDescriptor descriptor, object value) { Debug.Assert(dataset != null); Debug.Assert(descriptor != null); if (String.IsNullOrWhiteSpace(descriptor.TransformationForAggregationExpression)) { return(value); } var evaluator = new ExpressionEvaluator(dataset); evaluator.AddConstant(ExpressionEvaluator.IdentifierValue, value); evaluator.AddConstant(descriptor.Reference, value); // If there is an error in this expression then we accumulate a null value instead of untransformed // one because there are less chances it will cause more errors later. If option AggregationOptions.IgnoreAggregationErrors // is specified then Issues collection of the result dataset will contain this error for each accumulated value. return(evaluator.Evaluate(() => descriptor.TransformationForAggregationExpression)); }
public static object Sum(ValueDescriptor descriptor, CultureInfo culture, IEnumerable <object> values) { return(ToNumbers(descriptor, culture, values).Sum()); }
internal void AddWarning(ValueDescriptor item, string message) { Add(new DataError(IssueSeverity.Warning, item, message)); }
internal void AddValidationError(ValueDescriptor item, string message) { Add(new DataError(IssueSeverity.ValidationError, item, message)); }
internal void AddModelError(ValueDescriptor item, string message) { Add(new DataError(IssueSeverity.ModelError, item, message)); }
public static object Count(ValueDescriptor descriptor, CultureInfo culture, IEnumerable <object> values) { return(values.Count()); }