【问题标题】:Dynamic String Templating in C#C# 中的动态字符串模板
【发布时间】:2020-01-25 17:01:46
【问题描述】:

我正在寻找一种执行字符串插值的方法,但是模板字符串提前在变量中,而不是使用 true 字符串解释 $"{a}{b }" 立即参数化并返回。

这在很多地方都有用,但最明显的例子是,我正在编写一个 ETL(提取转换负载)管道,其中包含我需要使用的几十个不同的 REST API。相同的两个参数重复出现在不同的 URI 中,我想用用户提供的值动态替换它们。下面列出了两个这样的例子。

  • http://www.example.com/projects/{projectId}/data
    • 例如,给定projectId of 1,我希望http://www.example.com/projects/1/data
  • http://www.example.com/project/{projectId}/data?uploadId={uploadId}

如果我在运行时有可用的值,则可以使用字符串插值轻松完成此操作,例如“

int projectId = 1;
int uploadId = 3;
string uri = $"http://www.example.com/project/{projectId}/data?uploadId={uploadId}";
/* evaluates to "http://www.example.com/project/1/data?uploadId=1" */

但是,我想提前构建这些参数化字符串,并能够用我在该上下文中可用的任何变量替换它们。换句话说,在伪代码中:

int projectId = 1;
int uploadId = 3;
string uriTemplate = "http://www.example.com/project/{projectId}/data?uploadId={uploadId}";
string uri = ReplaceNameTags(uriTemplate, projectId, uploadId)
// example method signature
string ReplaceNametags(uriTemplate, params object[] args)
{
    /* insert magic here */
}

想到了反射,也许我可以以某种方式收集输入的名称,但我对反射不是很好,我所有的尝试最终都比完全放弃这个想法要复杂得多.

想到了String.Format(),但理想情况下我不会受到所提供参数的序数位置的限制。

我已经看到到处都在使用这种行为(例如 RestSharp、Swagger、ASP.NET Routing),但我不知道如何模仿它。

谢谢!

【问题讨论】:

  • 感谢 Anoop;有趣的是,这实际上非常接近我第一次尝试的样子,并且除了一些奇怪的例外(如字符串中的过度/不足替换标签),它运行得很好。但我不喜欢的是,我不得不在任何我想执行替换的地方创建一个新的字典,以及重新输入所有要替换的 slug。它是有效的,但并不简洁,并且好奇是否有更优雅的解决方案。也许是这种方法,但以更可重用的方式包装?
  • 也许只是 string uri = ReplaceNametags(uriTemplate, new object[] { projectId, uploadId}); 并更改 "http://www.example.com/project/{param0}/data?uploadId={param1}"; 中的占位符。然后在方法中循环args[]string.Replace()$"{{param{i}}}",如uriTemplate = uriTemplate.Replace($"{{param{i}}}", args[i].ToString());
  • 在这种情况下,我仍然会说字符串插值是你最好的选择。

标签: c# string formatting interpolation templating


【解决方案1】:

您可以将参数作为动态对象传递,遍历其键并利用正则表达式执行替换:

private string ReplaceNameTags(string uri, dynamic arguments)
    {
        string result = uri;
        var properties = arguments.GetType().GetProperties();
        foreach (var prop in properties)
        {
            object propValue = prop.GetValue(arguments, null);
            //result = Regex.Replace(uri, $"{{{prop.Name}}}", propValue.ToString());
              result = Regex.Replace(result, $"{{{prop.Name}}}", propValue.ToString());
        }
        return result;
    }

使用示例如下:

ReplaceNameTags(uri, new { projectId, uploadId });

【讨论】:

  • 我认为这正是我想要的;谢谢!
【解决方案2】:

您可以使用位置占位符代替变量名,并记录哪个变量位于哪个位置。

int projectId = 1; //documented as the first value (position 0)
int uploadId = 3; //documented as the second value (position 1)

//supplied by end users... say, loaded from config file
string uriTemplate = "http://www.example.com/project/{0}/data?uploadId={1}";

string uri = string.Format(uriTemplate, projectId, uploadId);

我还看到在位置 0 处使用空字符串完成此操作,因此当编号从 1 开始时,它对最终用户更有意义。

string uriTemplate = "http://www.example.com/project/{1}/data?uploadId={2}";
string uri = string.Format(uriTemplate, "", projectId, uploadId);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-08
    • 2023-03-21
    • 2011-06-09
    相关资源
    最近更新 更多