对于简单的值类型属性没问题了,但对于复杂一些类型如,如People的属性Son(Son就是儿子,我一开始写成了Sun),他也是一个People类型,他也有属性的,而且他也可能有Son...
先看下调用代码吧:
People p4 = new People { Id = 1, Name = "鹤冲天", Brithday = new DateTime(1990, 9, 9) };
p4.Son = new People { Id = 2, Name = "鹤小天", Brithday = new DateTime(2015, 9, 9) };
p4.Son.Son = new People { Id = 3, Name = "鹤微天", Brithday = new DateTime(2040, 9, 9) };
string s4 = p4.ToString4("[Name] 的孙子 [Son.Son.Name] 的生日是:[Son.Son.Brithday: yyyy年MM月dd日]。");
p4.Son = new People { Id = 2, Name = "鹤小天", Brithday = new DateTime(2015, 9, 9) };
p4.Son.Son = new People { Id = 3, Name = "鹤微天", Brithday = new DateTime(2040, 9, 9) };
string s4 = p4.ToString4("[Name] 的孙子 [Son.Son.Name] 的生日是:[Son.Son.Brithday: yyyy年MM月dd日]。");
“鹤冲天”也就是我了,有个儿子叫“鹤小天”,“鹤小天”有个儿子,也就是我的孙子“鹤微天”。哈哈,祖孙三代名字都不错吧(过会先把小天、微天这两个名字注册了)!主要看第4行,format是怎么写的。下面是版本四实现代码,由版本三改进而来:
public static string ToString4(this object obj, string format)
{
MatchEvaluator evaluator = match =>
{
string[] propertyNames = match.Groups["Name"].Value.Split('.');
string propertyFormat = match.Groups["Format"].Value;
object propertyValue = obj;
try
{
foreach (string propertyName in propertyNames)
propertyValue = propertyValue.GetPropertyValue(propertyName);
}
catch
{
return match.Value;
}
if (string.IsNullOrEmpty(format) == false)
return string.Format("{0:" + propertyFormat + "}", propertyValue);
else return propertyValue.ToString();
};
string pattern = @"\[(?[^\[\]:]+)(\s*[:]\s*(?[^\[\]:]+))?\]";
return Regex.Replace(format, pattern, evaluator, RegexOptions.Compiled);
}
{
MatchEvaluator evaluator = match =>
{
string[] propertyNames = match.Groups["Name"].Value.Split('.');
string propertyFormat = match.Groups["Format"].Value;
object propertyValue = obj;
try
{
foreach (string propertyName in propertyNames)
propertyValue = propertyValue.GetPropertyValue(propertyName);
}
catch
{
return match.Value;
}
if (string.IsNullOrEmpty(format) == false)
return string.Format("{0:" + propertyFormat + "}", propertyValue);
else return propertyValue.ToString();
};
string pattern = @"\[(?[^\[\]:]+)(\s*[:]\s*(?[^\[\]:]+))?\]";
return Regex.Replace(format, pattern, evaluator, RegexOptions.Compiled);
}
为了反射获取属性方法,用到了GetPropertyValue扩展如下(版本三的实现用上这个扩展会更简洁)(考虑性能请在此方法加缓存):
public static object GetPropertyValue(this object obj, string propertyName)
{
Type type = obj.GetType();
PropertyInfo info = type.GetProperty(propertyName);
return info.GetValue(obj, null);
}
{
Type type = obj.GetType();
PropertyInfo info = type.GetProperty(propertyName);
return info.GetValue(obj, null);
}
先执行,再分析:
执行正确! 版本四,8~17行用来层层获取属性。也不太复杂,不多作解释了。说明一下,版本四是不完善的,没有做太多处理。