2015-10-13 75 views
1

我們有一堆文本模板,這些模板是我們Visual Studio解決方案中的嵌入資源。加載和訪問文本文件中的模板變量

我用這樣一個簡單的方法來加載它們:

public string getTemplate() 
    { 
     var assembly = Assembly.GetExecutingAssembly(); 
     var templateName = "ResearchRequestTemplate.txt"; 
     string result; 

     using (Stream stream = assembly.GetManifestResourceStream(templateName)) 
     using (StreamReader reader = new StreamReader(stream)) 
     { 
      result = reader.ReadToEnd(); 
     } 
     return result; 
    } 

所以我可以加載上面的方法的文件,但我怎麼用變量替換文件中的模板變量I」已經在我的代碼中創建?這甚至有可能嗎?也許我會談論這一切錯誤...

ResearchRequestTemplate.txt: 

Hello { FellowDisplayName } 

You have requested access to the { ResearchProjectTitle } Project. 

    Please submit all paperwork and badge ID to { ResourceManagerDisplayName } 

謝謝!

回答

2

您可以使用一系列string.Replace()語句。

或者你也可以修改模板,並利用string.Format

Hello {0} 

You have requested access to the {1} Project. 

    Please submit all paperwork and badge ID to {2} 

後在模板中讀取,插入正確的價值觀:

return string.Format(
    result, fellowDisplayName, researchProjectTitle, resourceManagerDisplayName); 

這可能是有點容易出錯,如果模板經常變化,並且某人不小心確保模板中的編號與傳入參數的順序相匹配。

1

選項1 - 使用運行時文本模板


作爲一個優雅的解決方案,您可以使用Run-time Text Templates。添加運行文本模板的一個新的項目到項目,並命名該文件ResearchRequestTemplate.tt把這個內容是:

<#@ template language="C#" #> 
<#@ assembly name="System.Core" #> 
<#@ import namespace="System.Linq" #> 
<#@ import namespace="System.Text" #> 
<#@ import namespace="System.Collections.Generic" #> 
<#@ parameter name="FellowDisplayName" type="System.String"#> 
<#@ parameter name="ResearchProjectTitle" type="System.String"#> 
<#@ parameter name="ResourceManagerDisplayName" type="System.String"#> 
Hello <#= FellowDisplayName #> 

You have requested access to the <#= ResearchProjectTitle #> Project. 

    Please submit all paperwork and badge ID to <#= ResourceManagerDisplayName #> 

然後使用這種方式:

var template = new ResearchRequestTemplate(); 
template.Session = new Dictionary<string, object>(); 
template.Session["FellowDisplayName"]= value1; 
template.Session["ResearchProjectTitle"]= value2; 
template.Session["ResourceManagerDisplayName"] = value3; 
template.Initialize(); 
var result = template.TransformText(); 

這是一種非常靈活的方式和你可以簡單地擴展它,因爲visual studio爲你的模板生成一個C#類,例如你可以爲它創建一個部分類,並在其中添加一些屬性並簡單地使用類型化屬性。

選擇2 - 命名的String.Format


可以使用指定的字符串格式的方法:

這裏是an implementation by James Newton

public static class Extensions 
{ 
    public static string FormatWith(this string format, object source) 
    { 
     return FormatWith(format, null, source); 
    } 

    public static string FormatWith(this string format, IFormatProvider provider, object source) 
    { 
     if (format == null) 
     throw new ArgumentNullException("format"); 

     Regex r = new Regex(@"(?<start>\{)+(?<property>[\w\.\[\]]+)(?<format>:[^}]+)?(?<end>\})+", 
     RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase); 

     List<object> values = new List<object>(); 
     string rewrittenFormat = r.Replace(format, delegate(Match m) 
     { 
     Group startGroup = m.Groups["start"]; 
     Group propertyGroup = m.Groups["property"]; 
     Group formatGroup = m.Groups["format"]; 
     Group endGroup = m.Groups["end"]; 

     values.Add((propertyGroup.Value == "0") 
      ? source 
      : DataBinder.Eval(source, propertyGroup.Value)); 

     return new string('{', startGroup.Captures.Count) + (values.Count - 1) + formatGroup.Value 
      + new string('}', endGroup.Captures.Count); 
     }); 

     return string.Format(provider, rewrittenFormat, values.ToArray()); 
    } 
} 

和使用:

"{CurrentTime} - {ProcessName}".FormatWith(
    new { CurrentTime = DateTime.Now, ProcessName = p.ProcessName }); 

你也可以看看an implementation by Phil Haack

1

您可以使用正則表達式用一個簡單的替代方案:

var replacements = new Dictionary<string, string>() { 
    { "FellowDisplayName", "Mr Doe" }, 
    { "ResearchProjectTitle", "Frob the Baz" }, 
    { "ResourceManagerDisplayName", "Mrs Smith" }, 
}; 

string template = getTemplate();  
string result = Regex.Replace(template, "\\{\\s*(.*?)\\s*\\}", m => { 
    string value; 
    if (replacements.TryGetValue(m.Groups[1].Value, out value)) 
    { 
     return value; 
    } 
    else 
    { 
     // TODO: What should happen if we don't know what the template value is? 
     return string.Empty; 
    } 
}); 
Console.WriteLine(result);