Config Transformation Tool: Parameters support
- modified:
- reading: 3 minutes
Couple of weeks ago I wrote about my small utility Config Transformation Tool, which I wrote with base of web.config transformation task. In those moments I was thinking about opportunity to pass parameters to transform file, to tool can replaces parameters in transformation file with special values. Yesterday I resolved this issue. From now I use class Microsoft.Web.Publishing.Tasks.XmlTransformation which works with strings and XmlDocuments instead of files. I had two tasks: (a) I need method which will replace parameters on values, (b) I need method which will be parse command line and create dictionary of parameters.
ParametersTask
Let’s solve first task. I decided to use next syntax for parameters: {Parameter_Name:Default_Value}, where default value is optional. Rules for replace:
- If parameter defined with value – tool will use this value;
- If parameter not set, but value by default defined – tool will use default value;
- If parameter not set and default value not set – tool will leave this as is.
I didn’t want to solve this issue with RegEx or string.Replace methods, because if parameters will be many, execution of this task can take a long period. So I wanted to write method which will handle all parameters in string in one pass. Also I thought that maybe will need to use symbols ‘{’, ‘}’ in string, so I need way to escape these symbols. I decided to use combinations ‘\}’, “\{”, and if you want to use ‘\’ you should use combination ‘\\’. Ok, so class ParametersTask has one field _parameters with type IDictionary<string,string>, where keys are names of parameters, and values are values of parameters. Main method ApplyParameters:
```csharp public string ApplyParameters(string sourceString) { StringBuilder result = new StringBuilder(); int index = 0; char[] source = sourceString.ToCharArray(); bool fParameterRead = false; StringBuilder parameter = new StringBuilder(); while (index < source.Length) { // If parameter read, read it and replace it if (fParameterRead && source[index] == '}') { var s = parameter.ToString(); int colonIndex = parameter.ToString().IndexOf(':'); var parameterName = colonIndex > 0 ? s.Substring(0, colonIndex) : s; var parameterDefaultValue = colonIndex > 0 ? s.Substring(colonIndex + 1, s.Length - colonIndex - 1) : null; string parameterValue = null; if (_parameters != null && _parameters.ContainsKey(parameterName)) parameterValue = _parameters[parameterName]; // Put "value" or "default value" or "string which was here" result.Append(parameterValue ?? parameterDefaultValue ?? "{" + parameter + "}"); fParameterRead = false; index++; continue; } if (source[index] == '{') { fParameterRead = true; parameter = new StringBuilder(); index++; } // Check is this escape \{ \} \\ else if (source[index] == '\\') { var nextIndex = index + 1; if (nextIndex < source.Length) { var nextChar = source[nextIndex]; if (nextChar == '}' || nextChar == '{' || nextChar == '\\') { index++; } } } if (fParameterRead) parameter.Append(source[index]); else result.Append(source[index]); index++; } return result.ToString(); } ```In the while cycle we read parameter or just content of file. First if check that next char is end of parameter’s definition, second if check that next char is start of parameter’s definition. Next if escape special combinations “\{”, “\}” or “\\”. Of course it is not a full “Recursive descent parser”, but it looks good, and it is working with next tests:
```csharp [Test] public void ApplyParameters_Sample() { const string ExpectedResult = @"ParametersParser
Second issue – tool should parse parameters from command line. I decided to use a way which use MsBuild tool, or very similar to it. Parameters should be separated by ‘;’, name and value of parameter should be separated by ‘:’, if parameter’s value has space or ‘;’ you can quote it, also you can use ‘\”’ and ‘\\’ for escape symbols ‘”’ and ‘\’. Realization:
```csharp ///Very simple. In while cycle we read name of parameter of value of parameter. Of course you can solve this issue with split methods, but I decided to handle this string in one pass too. Some tests for this method:
```csharp ///Result
Ok, so let’s look on example. Source file (s.config):
```xmlTransform file, it contains two parameters, one is Parameter1, value of which is optional (default value is there), and parameter Test3Value:
```xmlCall tool from command line:
```bash ctt s:s.config t:t.config d:d.config p:Parameter1:True;Test3Value:"c:\Program Files\Test" ```As expected d.config:
```xmlTool has one more argument fpt – you can use this argument, if transform file contains parameters with default values and in command line you don’t set values for these parameters, so if you set this argument tool will set default values, in other way tool will not execute ParametersTask, because you don’t set list of parameters.
Summary
Maybe you can find a lot of bugs, so please if you see something or will see – just tell me. I will glad to get from you some advises for this tool. Source code and binary you can download from project site at CodePlex: http://ctt.codeplex.com, last version Config Transformation Tool v1.1.
See Also
- Config Transformation Tool: Теперь поддерживаются параметры
- Config Transformation Tool: Using XDT Transformation
- Config Transformation Tool: Используем XDT Transformation
- Wrox–Professional WCF 4–Windows Communication Foundation with .NET 4
- Wrox–Professional WCF 4–Windows Communication Foundation with .NET 4