An application uses an
IMetaExpressionFactory or an
IExpressionParser to create expressions. Let's investigate Quino's metadata-building API by trying to set a default value.
The simplest expression is, not surprisingly, a constant expression. An application might set the default value like this:
property.DefaultValueGenerator = new ConstantExpression(DateTime.UtcToday);
This is not the recommended way to go, though. It's much better to use the expression factory to build expressions. For that, an application can inject the
IMetaExpressionFactory into a metadata builder and use that.
property.DefaultValueGenerator = _expressionFactory.CreateConstant(DateTime.UtcToday);
In the same way, the application could use the parser to generate the expression, as shown below.
property.DefaultValueGenerator = _expressionParser.CreateExpression("UtcNow");
These approaches are a bit better since they use standard Quino tools to build expressions. Still, they suffer from the following drawbacks:
- Fluency: Setting the property this way doesn't allow for using the much-more concise fluent API
- Injection: Setting default values and using expressions is a pretty common operation. An application would end up injecting the expression factory and/or parser into nearly every metadata builder
- Ordering: The application must be very careful to build calculated properties after the properties on which the expression depends already exist. This is not always easy and can lead to convoluted builder code.
To address the fluency issue, there is a separate method where the builder can pass in the expression parser:
Let's now take a look at some of the convenience methods that Quino provides to address the injection and ordering issues.
To set a fixed value, an application can apply it directly using a constant value. Quino transforms this constant to an expression during model-finalization.
What sorcery is this, though? How does Quino set a default value without an expression factory?
The mechanism works as follows:
- Instead of setting the expression directly, Quino creates a lambda that will create the expression given a parser or factor and stores it in a temporary aspect on the metadata
- The application includes the
FallbackExpressionBuilder(included in the
- This builder finds all of the aforementioned aspects (anything descended from
IFinalizeExpressionAspect) and applies it, passing in the expression parser and factory.
- After applying, the aspect is removed
This works extremely well and lets applications use very minimal code for constructing calculated properties.
There is one drawback versus using the parser or factory directly: if there is an error in parsing the expression, the exception is thrown during finalization rather than immediately. Quino provides a lot of context information to improve finding errors, though.