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:
StringValuewraps astringNumberValuewraps adecimalDateTimeValuewraps aDateTimeOffsetObjectValuewraps an object (all Fluid Values extend from this)BooleanValuewraps aboolArrayValuewraps aFluidValue[]DictionaryValuewraps a dictionary interfaceBlankValue,NilValue,EmptyValuedon’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
Typeproperty which describes what the value is – a String, Number, etc.A method called
WriteTowhich will write out whatever the value should generate. This is where the actual output is generatedA method called
GetValuewhich 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
GetIndexthat is passed when an index is called (ex:people[0]). It gets aFluidValue(aNumberValuein the example), and you can use this to lookup and return any value you like.A method called
Enumerateusing which you can return anIEnumerable<FluidValue>to be use to iterate values using afortagMethods 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 awesomeWe 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.