首页 > 解决方案 > 使用来自对象的参数格式化字符串

问题描述

我的数据库中有一个 varchar 列,上面有这样的数据:

"Hello my name is {person.firstname} and my house is in {city.name}"

我想在这个字符串中注入我的对象,以获得一个完整的数据字符串,其中填充来自数据库的数据。

我正在使用.Net 4.7它,它在一个 API 上。

这很容易吗?我需要使用 Roselyn 代码分析吗?

谢谢 !

标签: c#.net

解决方案


对于给定的字符串source

  string source = 
    "Hello my name is {person.firstname} and my house is in {city.name}";

我们必须实施2步骤:首先,我们应该能够为给定的名称(例如person.firstnamecity.name)提供正确的响应(例如,"John""New York")。如果您有某种上下文,要查询的实例集合,例如

  IEnumerable<object> = new List<object>() {
    new Person() {
      FirstName = "John",
      LastName  = "Smith",
      Sex       = "M",
      Age       = 44  
    },

    new City() {
      Name    = "New York",
      Country = "USA"
    },

    ...  
  };

你可以这样说:

private static string MakeResponse(IEnumerable<object> context, string name) {
  if (string.IsNullOrEmpty(name))
    return "???";
  else if (context == null)
    return "???";

  string[] items = name.Split('.');

  string className = items[0];
  string propertyName = items.Length > 1 ? items[1] : null;

  object data = context
    .Where(item => item != null)
    .FirstOrDefault(item => 
       string.Equals(item.GetType().Name, className, StringComparison.OrdinalIgnoreCase));

  if (null == data)
    return "???";

  if (null == propertyName)
    return data.ToString();

  var property = data
    .GetType()
    .GetProperties(BindingFlags.Public | 
                   BindingFlags.Instance | 
                   BindingFlags.Static)
    .Where(prop => string.Equals(prop.Name, propertyName, StringComparison.OrdinalIgnoreCase))
    .Where(prop => prop.CanRead)
    .Where(prop => !prop.GetIndexParameters().Any())
    .FirstOrDefault();

  if (null == property)
    return "???";

  return property.GetValue(property.GetGetMethod().IsStatic ? null : data)?.ToString() ?? "";
}

然后我们必须解析字符串,并替换{...}

private static string ReplaceMyMask(string source, params object[] context) {
  if (null == context)
    return source;

  return Regex.Replace(
    source,
  @"\{\s*[A-Za-z][A-Za-z0-9_]*(?:\.[A-Za-z][A-Za-z0-9_]*)*\s*}",
    match => MakeResponse(context, match.Value.Trim(' ', '{', '}'))
  );
}

演示:

public class Person {
  public string FirstName { get; set; }
  public string LastName { get; set; }
}

public class City {
  public string Name { get; set; }
}

...

var person = new Person() {
  FirstName = "John",
  LastName = "Smith",
},

var city = new City() {
  Name = "New York"
};

...

string stringToModify = 
  "Hello my name is {person.firstname} and my house is in {city.name}"; 

string result = ReplaceMyMask(stringToModify, person, city);

Console.Write(result);

结果:

Hello my name is John and my house is in New York

推荐阅读