Skip to content

Placeholders and Nesting

phexus edited this page Jan 10, 2024 · 11 revisions

Named placeholders

string.Format references all args by index:
string.Format("{0} {1}", person.FirstName, person.LastName)

SmartFormat takes this a step further, and lets you use named placeholders instead:
Smart.Format("{FirstName} {LastName}", person)

In fact, SmartFormat supports several kinds of expressions (parameterless methods): Smart.Format("{FirstName.ToUpper} {LastName.ToLower}", person)
where ToUpper is a parameterless method.

Nesting

var person = new
{
    Person = new
    {
        FirstName = "John",
        LastName = "Long",
        Address = new { City = "London" }
    }
};

In SmartFormat, you can use nesting to avoid repetition, such as:

Smart.Format("City: {Person:{Address:{City}}, Name: {FirstName}}", person);
// Outputs: "City: London, Name: John"

Nesting is often used with conditionals, plurals, and lists:

var data = new 
{
    People = new List<object> 
    {
        new {Name = "Name 1", Age = 20}
    }
};
Smart.Format("There {People.Count:is a person.|are {} people.}", data);
// Outputs: "There is a person."

// After adding one more item to the People list:
// Outputs: "There are 2 people."

Nested Scope

When using nested placeholders, it is necessary to understand the scope that SmartFormat will use. A nested placeholder always starts off with the scope of the item that contains it.

The root scope for the template above is data, meaning that {User.Address} is equivalent to data.User.Address.

Within the nested area, however, the "scope" has changed to User.Address, so nested expressions like {Street} are evaluated against User.Address.

To illustrate this, the following are all equivalent:

  • {User.Name} {User.Address.City} {User.Address.State}
  • {User.Name} {User.Address:{City} {State}}
  • {User:{Name} {Address:{City} {State}}}

Within any nested scope, you still have access to the outer scopes. For example:
{User.Address:{User.Name} {City} {State}}
Here, {User.Name}, which is in the root scope, is still accessible from within the nested User.Address scope.

In the example above you'll notice the empty placeholder {}. It uses the scope of People.Count and outputs its value.

Clone this wiki locally