使用反射将模板占位符替换为对象属性
Replace template Placeholder with Object Properties with Reflection
在 C# 中,我想使用反射将字符串占位符替换为对象属性
string formula = "{\"Name\": \"{{Name}}\", \"Email\": \"{{Email}}\" }";
Student student = new Student();
student.Name = "Parker";
student.Email = "Parker@xyz.com";
student.Address = "Mark Avenue";
var result1 = GenerateJson(formula, student);
//Output : "{\"Name\": \"Parker\", \"Email\": \"Parker@xyz.com\" }"
student.Name = "Royal";
student.Email = "Royal@xyz.com";
student.Address = "Cross Lane";
var result2 = GenerateJson(formula, student);
//Output : "{\"Name\": \"Royal\", \"Email\": \"Royal@xyz.com\" }"
public string GenerateJson(string formula, Student student)
{
string result = "";
//logic for replacing the Placeholder woth object properties
return result;
}
class Student
{
public string Name { get; set; }
public string Email { get; set; }
public string Address { get; set; }
}
您可以将其反序列化为 ExpandoObject
(IDictionary<string,object>
)。然后将 属性 个名称与已知类型进行比较。如果词典的键和学生的 属性姓名匹配。将 ExpandoObject
的值替换为 Student
的 属性 的值。毕竟序列化为json.
在这里,
public string GenerateJson(string formula, Student student)
{
IDictionary<string, object> templateValues = JsonConvert.DeserializeObject<IDictionary<string, object>>(formula);
PropertyInfo[] sourceProperty = typeof(Student).GetProperties();
foreach (var item in sourceProperty)
{
KeyValuePair<string,object> value = templateValues.FirstOrDefault(x=> x.Key == item.Name);
if (value.Key != null)
{
templateValues[item.Name] = item.GetValue(student);
}
}
return JsonConvert.SerializeObject(templateValues);
}
如果您真的不想或不能使用 Json.NET
,您可以尝试下面的解决方案
public string GenerateJson(string formula, Student student)
{
return Regex.Replace(formula, @"\{\{(\w+)\}\}", match => typeof(Student).GetProperty(
match.Groups[1].ToString())?.GetValue(student)?.ToString());
}
看起来实际问题是检索特定属性的值以生成 API 签名。尚不清楚签名是否真的需要 JSON 字符串。
最简单的方法是创建一个具有必要属性的匿名类型并将其序列化,例如:
var payload=JsonConvert.Serialize(new {student.Name,student.Email});
这比任何反射代码都快得多,并且只分配一个额外的对象。如果要将 API 与 lot 的不同请求类型一起使用,则需要使用代码生成器或在 C# 9 中使用源代码生成器来生成此类调用。
可以(但很慢)使用反射来检索特定属性,例如:
var dict=typeof(Student).GetProperties()
.Where(prop=>myProps.Contains(prop.Name))
.ToDictionary(prop=>prop.Name,prop=>prop.GetValue(student));
var json=JsonConvert.Serialize(dict);
JSON 对象实际上是一个字典,因此序列化字典的行为类似于序列化具有相同属性的对象。
尽管反射相对昂贵,所以缓存您想要的 PropertyInfo
对象并重用它们是个好主意:
Dictionary<Type,PropertyInfo[]> _properties=new Dictionary<Type,PropertyInfo[]>();
...
string GenerateJson<T>(T item)
{
PropertyInfo[] props;
if (!_properties.TryGetValue(typeof(T),out props))
{
props=typeof(Student).GetProperties()
.Where(prop=>myProps.Contains(prop.Name))
.ToArray();
}
var dict=props.ToDictionary(prop=>prop.Name,prop=>prop.GetValue(item));
return JsonConvert.Serialize(dict);
}
在 C# 中,我想使用反射将字符串占位符替换为对象属性
string formula = "{\"Name\": \"{{Name}}\", \"Email\": \"{{Email}}\" }";
Student student = new Student();
student.Name = "Parker";
student.Email = "Parker@xyz.com";
student.Address = "Mark Avenue";
var result1 = GenerateJson(formula, student);
//Output : "{\"Name\": \"Parker\", \"Email\": \"Parker@xyz.com\" }"
student.Name = "Royal";
student.Email = "Royal@xyz.com";
student.Address = "Cross Lane";
var result2 = GenerateJson(formula, student);
//Output : "{\"Name\": \"Royal\", \"Email\": \"Royal@xyz.com\" }"
public string GenerateJson(string formula, Student student)
{
string result = "";
//logic for replacing the Placeholder woth object properties
return result;
}
class Student
{
public string Name { get; set; }
public string Email { get; set; }
public string Address { get; set; }
}
您可以将其反序列化为 ExpandoObject
(IDictionary<string,object>
)。然后将 属性 个名称与已知类型进行比较。如果词典的键和学生的 属性姓名匹配。将 ExpandoObject
的值替换为 Student
的 属性 的值。毕竟序列化为json.
在这里,
public string GenerateJson(string formula, Student student)
{
IDictionary<string, object> templateValues = JsonConvert.DeserializeObject<IDictionary<string, object>>(formula);
PropertyInfo[] sourceProperty = typeof(Student).GetProperties();
foreach (var item in sourceProperty)
{
KeyValuePair<string,object> value = templateValues.FirstOrDefault(x=> x.Key == item.Name);
if (value.Key != null)
{
templateValues[item.Name] = item.GetValue(student);
}
}
return JsonConvert.SerializeObject(templateValues);
}
如果您真的不想或不能使用 Json.NET
,您可以尝试下面的解决方案
public string GenerateJson(string formula, Student student)
{
return Regex.Replace(formula, @"\{\{(\w+)\}\}", match => typeof(Student).GetProperty(
match.Groups[1].ToString())?.GetValue(student)?.ToString());
}
看起来实际问题是检索特定属性的值以生成 API 签名。尚不清楚签名是否真的需要 JSON 字符串。
最简单的方法是创建一个具有必要属性的匿名类型并将其序列化,例如:
var payload=JsonConvert.Serialize(new {student.Name,student.Email});
这比任何反射代码都快得多,并且只分配一个额外的对象。如果要将 API 与 lot 的不同请求类型一起使用,则需要使用代码生成器或在 C# 9 中使用源代码生成器来生成此类调用。
可以(但很慢)使用反射来检索特定属性,例如:
var dict=typeof(Student).GetProperties()
.Where(prop=>myProps.Contains(prop.Name))
.ToDictionary(prop=>prop.Name,prop=>prop.GetValue(student));
var json=JsonConvert.Serialize(dict);
JSON 对象实际上是一个字典,因此序列化字典的行为类似于序列化具有相同属性的对象。
尽管反射相对昂贵,所以缓存您想要的 PropertyInfo
对象并重用它们是个好主意:
Dictionary<Type,PropertyInfo[]> _properties=new Dictionary<Type,PropertyInfo[]>();
...
string GenerateJson<T>(T item)
{
PropertyInfo[] props;
if (!_properties.TryGetValue(typeof(T),out props))
{
props=typeof(Student).GetProperties()
.Where(prop=>myProps.Contains(prop.Name))
.ToArray();
}
var dict=props.ToDictionary(prop=>prop.Name,prop=>prop.GetValue(item));
return JsonConvert.Serialize(dict);
}