C#Reflection:用文本中的值替换所有出现的属性

Aqd*_*das 5 .net c# reflection c#-4.0

我有一个类似的课程

public class MyClass {

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

}
Run Code Online (Sandbox Code Playgroud)

案例是,我有一个字符串文本,如,

string str = "My Name is @MyClass.FirstName @MyClass.LastName";
Run Code Online (Sandbox Code Playgroud)

我想要的是将@ MyClass.FirstName@ MyClass.LastName替换为使用反射的值,这些值分配给类中的对象FirstName和LastName.

有什么帮助吗?

Dmi*_*nko 6

如果要生成可用于Linq枚举属性的字符串:

  MyClass test = new MyClass {
    FirstName = "John",
    LastName = "Smith",
  };

  String result = "My Name is " + String.Join(" ", test
    .GetType()
    .GetProperties(BindingFlags.Public | BindingFlags.Instance)
    .Where(property => property.CanRead)  // Not necessary
    .Select(property => property.GetValue(test)));

  // My Name is John Smith
  Console.Write(result);
Run Code Online (Sandbox Code Playgroud)

如果你想在字符串中进行替换(格式化),可以选择正则表达式来解析字符串:

  String original = "My Name is @MyClass.FirstName @MyClass.LastName";
  String pattern = "@[A-Za-z0-9\\.]+";

  String result = Regex.Replace(original, pattern, (MatchEvaluator) ((match) => 
    test
      .GetType()
      .GetProperty(match.Value.Substring(match.Value.LastIndexOf('.') + 1))
      .GetValue(test) 
      .ToString() // providing that null can't be returned
  ));

  // My Name is John Smith
  Console.Write(result);
Run Code Online (Sandbox Code Playgroud)

注意,为了获得实例(即非static)属性值,您必须提供实例(test在上面的代码中):

   .GetValue(test) 
Run Code Online (Sandbox Code Playgroud)

所以字符串中的@MyClass部分是无用的,因为我们可以直接从实例获取类型:

   test.GetType()
Run Code Online (Sandbox Code Playgroud)

编辑:如果某些属性可以null作为值返回

 String result = Regex.Replace(original, pattern, (MatchEvaluator) ((match) => {
   Object v = test
     .GetType()
     .GetProperty(match.Value.Substring(match.Value.LastIndexOf('.') + 1))
     .GetValue(test);

   return v == null ? "NULL" : v.ToString(); 
 }));
Run Code Online (Sandbox Code Playgroud)


Kva*_*vam 5

首先,我建议不要在string.Format可能的情况下使用反射。反射会降低代码的可读性和维护难度。无论哪种方式,你都可以这样做:

public void Main()
{
    string str = "My Name is @MyClass.FirstName @MyClass.LastName";
    var me = new MyClass { FirstName = "foo", LastName = "bar" };
    ReflectionReplace(str, me);
}

public string ReflectionReplace<T>(string template, T obj)
{    
    foreach (var property in typeof(T).GetProperties())
    {
        var stringToReplace = "@" + typeof(T).Name + "." + property.Name;
        var value = property.GetValue(obj);
        if (value == null) value = "";
        template = template.Replace(stringToReplace, value.ToString());
    }
    return template;
}
Run Code Online (Sandbox Code Playgroud)

如果您想向类添加新属性并更新模板字符串以包含新值,则不需要额外更改。它还应该处理任何类的任何属性。