Resolving Variables in Text

(Initial, informal version; updated version to come.)

New in 15.1 is a standard class for resolving "variables" in a body of text. The class is Asi.VariableResolver (in Asi.dll). It's pretty simple; you give it a body of text, with variables (denoted by []) included, and pass it either a set of Name/Value pairs, a list of IAtom objects, or both, and it returns the text with all the matched variables replaced by their respective values.

The XML docs are pretty good for that class, but here's a quick overview:

Variables take the form of [VariableName], [ObjectName.VariableName], or [ObjectIndex.VariabledName] and are resolved thus:

Variable Form Variable Substituted by
[VariableName] The value included in the NameValueCollection where the key = VariableName
[ObjectName.VariableName] The IAtom list is searched for an object whose AtomTypeName (BusinessControllerName) is ObjectName, and the value of the property whose name is VariableName is used as the value.
[ObjectIndex.VariableName] The IAtom at the position in the IAtom list given by ObjectIndex is used to retrieve the value of the property whose name is VariableName. ObjectIndex is 0-based.

So, for example, if I have the source text "Hello, [Name] and welcome to [Event.Name], [2.Description]" and I pass in the following:

  • A NameValueCollection that contains the name/value pair "Name"/"Bob Smith"
  • An IAtom list consisting of:
    • An Event object (Name = "PDC 2009")
    • A Contact object
    • A Function object (Description = "My Function")

    (in that order)

Then the resulting text will be:

Hello, Bob Smith and welcome to PDC 2008, My Function

A couple of other things to note -- by default, if there's a variable in the text that isn't satisfied by any of the passed-in values, it throws an ArgumentException. You can disable this by passing false for the foundOnlyVariables parameter; I'm not sure whether passing true (to prevent an e-mail going out with [VariableStuff] still in it, for example) or false (to be more lenient) is better for this usage. Also, to escape any items in square brackets that you don't want to be treated as variables, double up the brackets (i.e. [ [ Name ] ] (without spaces)) and the resolver will replace them with single (i.e. [Name]) in the output.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

The only concern I have is with []

All things considered, are square brackets the best choice?  Square brackets have intrinsic meanings which could overlap:

*  Written english, as nested parenthesis (which few people use consistently [but it is correct usage]).

*  Written english, to provide context or abbreviate quotations.  "He bemoaned the day he lost it." written as "He bemoaned the day he lost [his hair]."

SQL, for pattern matching.  select * from Name where LAST_FIRST 

like 'C[OU]TTER%'  returns all records beginning with COTTER or CUTTER.  select * from Name where LAST_FIRST like '[A-M]%' returns all records starting with letters A-M.

Would curly brackets be a safer choice?  They also have intrinsic meanings in C# and other languages, but the intrinsic meaning is very similar: substitution.

-- Bruce

Any character has possible

Any character has possible collisions, unfortunately. There is an option to ignore values which don't match any provided variables, and it is possible to "escape" the brackets by doubling them up (i.e. this will results in [this will] in the output), so all of the above examples can be dealt with reasonably easily.

Square brackets had already been used in similar contexts, and this code was written to complement the existing usages, so square brackets were used.