public override ValueTask <FluidValue> GetValueAsync(string name, TemplateContext context) { return(name switch { "length" => new ValueTask <FluidValue>(NumberValue.Create(Length)), "index" => new ValueTask <FluidValue>(NumberValue.Create(Index)), "index0" => new ValueTask <FluidValue>(NumberValue.Create(Index0)), "rindex" => new ValueTask <FluidValue>(NumberValue.Create(RIndex)), "rindex0" => new ValueTask <FluidValue>(NumberValue.Create(RIndex0)), "first" => new ValueTask <FluidValue>(BooleanValue.Create(First)), "last" => new ValueTask <FluidValue>(BooleanValue.Create(Last)), _ => new ValueTask <FluidValue>(NilValue.Instance), });
public static FluidValue Create(object value, TemplateOptions options) { if (value == null) { return(NilValue.Instance); } if (value is FluidValue fluidValue) { return(fluidValue); } if (options.ValueConverters.Count > 0) { foreach (var valueConverter in options.ValueConverters) { var result = valueConverter(value); if (result != null) { // If a converter returned a FluidValue instance use it directly if (result is FluidValue resultFluidValue) { return(resultFluidValue); } // Otherwise stop custom conversions value = result; break; } } } var typeOfValue = value.GetType(); switch (System.Type.GetTypeCode(typeOfValue)) { case TypeCode.Boolean: return(BooleanValue.Create(Convert.ToBoolean(value))); case TypeCode.Byte: case TypeCode.UInt16: case TypeCode.UInt32: return(NumberValue.Create(Convert.ToUInt32(value))); case TypeCode.SByte: case TypeCode.Int16: case TypeCode.Int32: return(NumberValue.Create(Convert.ToInt32(value))); case TypeCode.UInt64: case TypeCode.Int64: case TypeCode.Decimal: case TypeCode.Double: case TypeCode.Single: return(NumberValue.Create(Convert.ToDecimal(value))); case TypeCode.Empty: return(NilValue.Instance); case TypeCode.Object: switch (value) { case DateTimeOffset dateTimeOffset: return(new DateTimeValue(dateTimeOffset)); case IDictionary <string, object> dictionary: return(new DictionaryValue(new ObjectDictionaryFluidIndexable(dictionary, options))); case IDictionary <string, FluidValue> fluidDictionary: return(new DictionaryValue(new FluidValueDictionaryFluidIndexable(fluidDictionary))); case IDictionary otherDictionary: return(new DictionaryValue(new DictionaryDictionaryFluidIndexable(otherDictionary, options))); case FluidValue[] array: return(new ArrayValue(array)); case IList <FluidValue> list: return(new ArrayValue(list)); case IEnumerable <FluidValue> enumerable: return(new ArrayValue(enumerable)); case IList list: var values = new List <FluidValue>(list.Count); foreach (var item in list) { values.Add(Create(item, options)); } return(new ArrayValue(values)); case IEnumerable enumerable: var fluidValues = new List <FluidValue>(); foreach (var item in enumerable) { fluidValues.Add(Create(item, options)); } return(new ArrayValue(fluidValues)); } return(new ObjectValue(value)); case TypeCode.DateTime: return(new DateTimeValue((DateTime)value)); case TypeCode.Char: case TypeCode.String: return(new StringValue(Convert.ToString(value, CultureInfo.InvariantCulture))); default: throw new InvalidOperationException(); } }
public static FluidValue Create(object value) { if (value == null) { return(NilValue.Instance); } if (value is FluidValue fluidValue) { return(fluidValue); } var typeOfValue = value.GetType(); // First check for a specific type conversion before falling back to an automatic one var mapping = GetTypeMapping(typeOfValue); if (mapping != null) { return(mapping(value)); } switch (System.Type.GetTypeCode(typeOfValue)) { case TypeCode.Boolean: return(BooleanValue.Create(Convert.ToBoolean(value))); case TypeCode.Decimal: case TypeCode.Double: case TypeCode.Single: return(NumberValue.Create(Convert.ToDouble(value))); case TypeCode.SByte: case TypeCode.Byte: case TypeCode.Int16: case TypeCode.Int32: case TypeCode.Int64: case TypeCode.UInt16: case TypeCode.UInt32: case TypeCode.UInt64: return(NumberValue.Create(Convert.ToDouble(value), true)); case TypeCode.Empty: return(NilValue.Instance); case TypeCode.Object: if (value == null) { return(NilValue.Instance); } switch (value) { case FluidValue fluid: return(fluid); case DateTimeOffset dateTimeOffset: return(new DateTimeValue(dateTimeOffset)); case IDictionary <string, object> dictionary: return(new DictionaryValue(new ObjectDictionaryFluidIndexable(dictionary))); case IDictionary <string, FluidValue> fluidDictionary: return(new DictionaryValue(new FluidValueDictionaryFluidIndexable(fluidDictionary))); case IDictionary otherDictionary: return(new DictionaryValue(new DictionaryDictionaryFluidIndexable(otherDictionary))); case IList <FluidValue> list: return(new ArrayValue(list)); case IEnumerable <FluidValue> enumerable: return(new ArrayValue(enumerable)); case IEnumerable enumerable: var fluidValues = new List <FluidValue>(); foreach (var item in enumerable) { fluidValues.Add(Create(item)); } return(new ArrayValue(fluidValues)); } return(new ObjectValue(value)); case TypeCode.DateTime: return(new DateTimeValue((DateTime)value)); case TypeCode.Char: case TypeCode.String: return(new StringValue(Convert.ToString(value, CultureInfo.InvariantCulture))); default: throw new InvalidOperationException(); } }