Fluid Values
Fluid only deals in FluidValue
objects. Everything you inject into a scope will be converted into a FluidValue
object. Indeed, the properties dictionary on Scope
only holds FluidValue
objects.
There’s a method on TemplateContext
that takes a string and a FluidValue
:
context.SetValue("name", StringValue.Create("Deane"));
(I know, I know – we haven’t been explicitly creating FluidValue
objects in prior examples. We’ll explain this when we get to Value Convertors.)
Here are the built-in Fluid values:
StringValue
wraps astring
NumberValue
wraps adecimal
DateTimeValue
wraps aDateTimeOffset
ObjectValue
wraps an object (all Fluid Values extend from this)BooleanValue
wraps abool
ArrayValue
wraps aFluidValue[]
DictionaryValue
wraps a dictionary interfaceBlankValue
,NilValue
,EmptyValue
don’t wrap anything, but exist for conditional checking
Most of the provided classes have a private field for _value
which holds whatever the original value was.
Fluid Values provide a common interface. Some highlights:
A
Type
property which describes what the value is – a String, Number, etc.A method called
WriteTo
which will write out whatever the value should generate. This is where the actual output is generatedA method called
GetValue
which will produce a value. Often, this is just the underlying value that’s being wrapped, but as we’ll see later, it can create a value a number of different waysA method called
GetIndex
that is passed when an index is called (ex:people[0]
). It gets aFluidValue
(aNumberValue
in the example), and you can use this to lookup and return any value you like.A method called
Enumerate
using which you can return anIEnumerable<FluidValue>
to be use to iterate values using afor
tagMethods to convert the Fluid Value into various primitives – numbers, string, etc.
So long as you provide this functionality, you can create your own values. For example, if we wanted to value that wrapped a string and appended “ is awesome” to it when it output, we could do this:
public class AwesomeValue : FluidValue
{
private string _value;
public AwesomeValue(string value)
{
_value = value;
}
public override void WriteTo(TextWriter writer, TextEncoder encoder, CultureInfo cultureInfo) => writer.Write(ToStringValue());
public override string ToStringValue() => $"{_value} is awesome";
// We don't really care about any of this, but FluidValue is
// abstract, so we have to override it all
public override FluidValues Type => FluidValues.String;
public override bool Equals(FluidValue other) => false;
public override bool ToBooleanValue() => false;
public override decimal ToNumberValue() => 0;
public override object ToObjectValue() => ToStringValue();
}
When we set this value in the context –
context.SetValue("name", new AwesomeValue("Deane"));
– it will output this wherever it appears:
Deane is awesome
We pushed an AwesomeValue
into the Context, and it was placed in the Scope. When a template finds it, the WriteTo
method will create the desired output.