在文本文件中加载和访问模板变量

时间:2015-10-13 20:15:39

标签: c# .net c#-4.0

我们的视觉工作室解决方案中嵌入了大量文本模板。

我正在使用这样一个简单的方法来加载它们:

    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;
    }

所以我可以使用上面的方法加载文件,但是如何用我在代码中创建的变量替换文件中的模板变量?这甚至可能吗?也许我说这一切都错了......

ResearchRequestTemplate.txt:

Hello { FellowDisplayName }

You have requested access to the { ResearchProjectTitle } Project.

    Please submit all paperwork and badge ID to { ResourceManagerDisplayName }

谢谢!

3 个答案:

答案 0 :(得分: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)

选项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#类,例如你可以为它创建一个部分类,并在其中放入一些属性并简单地使用类型属性。 / p>

选项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

答案 2 :(得分: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);