【问题标题】:How to make String Interpolation work with dictionary如何使字符串插值与字典一起使用
【发布时间】:2018-09-11 16:53:53
【问题描述】:

我有一个带有key value pair的字典,我需要使用字符串插值,然后根据命名参数映射字符串。请帮我。

// code removed for brevity
var rawmessage = "Hello my name is {Name}"; // raw message
var dict= new Dictionary<string, object>();
dict.Add("{Name}", response.Name);

我希望能够做类似的事情:

// Pseudo code
$"Hello my name is {Key}", dict;

到目前为止我找到的解决方案:

     var message = parameters.Aggregate(message, 
(current, parameter) => current.Replace(parameter.Key, parameter.Value.ToString()));

它工作正常,但我的经理真的希望我使用带有字典的字符串插值。我不确定如何实现这一目标。请指导我。

【问题讨论】:

  • 字符串插值只是string.Format周围的语法糖,不能像这样使用预设字符串。
  • @DavidG 如果你有一个带键值的字典和一个带命名参数的字符串,那么你将如何映射它?
  • 您的最后一段代码确实是唯一的方法。虽然如果您有很多替换要做,您可能需要考虑使用StringBuilder 来提高性能。
  • 现在,为什么要投反对票!说真的!
  • 不是来自我,这是一个有效的问题,只是无法实现。

标签: c# .net string


【解决方案1】:

问题是 C# 中的 string interpolation 只是 string.Format 的语法糖包装器。字符串被编译为相同的代码。以这段代码为例:

public string GetGreeting1(string name)
{
    return string.Format("Hello {0}!", name);
}

public string GetGreeting2(string name)
{
    return $"Hello {name}!";
}

两种方法的 IL 输出是相同的:

GetGreeting1:
IL_0000:  ldstr       "Hello {0}!"
IL_0005:  ldarg.1     
IL_0006:  call        System.String.Format
IL_000B:  ret         

GetGreeting2:
IL_0000:  ldstr       "Hello {0}!"
IL_0005:  ldarg.1     
IL_0006:  call        System.String.Format
IL_000B:  ret  

因此,您拥有的解决方案是完全有效的,并且我以前使用过。唯一可能的改进是如果您打算进行大量替换,如果您改用StringBuilder,您可能会发现性能优势。您可能会在 Nuget 上找到一个库来为您做这件事,但这对于您的目的来说可能有点矫枉过正。

另外,我为此做了一个扩展类。额外的好处是,我还添加了一种使用具有任意数量参数的对象的方法,该方法使用反射来进行替换:

public static class StringReplacementExtensions
{
    public static string Replace(this string source, Dictionary<string, string> values)
    {
        return values.Aggregate(
            source,
            (current, parameter) => current
                .Replace($"{{{parameter.Key}}}", parameter.Value));
    }

    public static string Replace(this string source, object values)
    {
        var properties = values.GetType().GetProperties();

        foreach (var property in properties)
        {
            source = source.Replace(
                $"{{{property.Name}}}", 
                property.GetValue(values).ToString());
        }

        return source;
    }
}

并像这样使用:

var source = "Hello {name}!";

//Using Dictionary:
var dict = new Dictionary<string, string> { { "name", "David" } };
var greeting1 = source.Replace(dict);
Console.WriteLine(greeting1);

//Using an anonymous object:
var greeting2 = source.Replace(new { name = "David" });
Console.WriteLine(greeting2);

【讨论】:

    【解决方案2】:

    它工作正常,但我的经理真的希望我使用带有字典的字符串插值。我不确定如何实现这一点。

    你不能那样做。 C# 插值字符串不是模板引擎,而是编译时功能,可转换为 String.Format 调用。这就是为什么你也不能在常量表达式中使用字符串插值。

    我想使用字符串插值将命名参数(在字典中作为键存在)映射到它们各自的值。但我不想使用 String.Replace。有什么办法吗?

    实际上,您可以使用多种模板引擎(主要用于日志记录),因此您无需重新发明轮子。例如,您可能会觉得 Serilog 很有趣。

    另请参阅此线程:What's a good way of doing string templating in .NET?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-10-26
      • 2012-05-20
      • 1970-01-01
      • 1970-01-01
      • 2018-01-01
      • 2016-04-24
      • 2019-09-15
      • 1970-01-01
      相关资源
      最近更新 更多