【发布时间】:2021-08-18 16:18:05
【问题描述】:
我有一个 C# 代码,它会查看类上的每个公共属性并创建键和值的集合。关键是访问属性的简单点符号变量;
我有以下型号
public class Home
{
public string Id { get; set; }
public string Summary { get; set; }
public Address Address { get; set; }
}
public class Address
{
public Street Street { get; set; }
public string CityName { get; set; }
public string StateName { get; set; }
}
public class Street
{
public string Number { get; set; }
public string Name { get; set; }
}
那我有下面的功能
public void GetPropertyKeyValue<T>(T obj, string prefix, List<ExtractedTerm> pairs)
{
if (pairs == null)
{
throw new ArgumentNullException(nameof(pairs));
}
// This works of the first object, but fails on the class properties
var properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var property in properties)
{
string key = property.Name;
if (!string.IsNullOrWhiteSpace(prefix))
{
key = $"{prefix}.{property.Name}";
}
Type type = property.PropertyType;
object value = property.GetValue(obj, null);
if (type.IsClass && !type.IsInterface && !type.IsEnum && !type.IsPrimitive && !type.IsString())
{
GetPropertyKeyValue(value, key, ref pairs);
continue;
}
pairs.Add(new ExtractedTerm(key, value, property.PropertyType));
}
}
上面的方法是这样调用的
var home = new Home() {
Id = "100",
Summary = "Test",
Address = new Address() {
CityName = "Los Angeles"
}
}
var pairs = new List<ExtractedTerm>();
GetPropertyKeyValue(home, null, pairs);
上面的代码在Home.Id 和Home.Summary 和Home.Address 上完美运行但是因为Address 是类类型的属性,所以GetPropertyKeyValue 方法被递归调用。当Address 被传递时,代码typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance) 不返回任何属性。但是,代码 obj.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance) 返回预期的属性。但我不能真正指望obj.GetType(),因为 obj 可能为空。正如您在上面的示例中注意到的,Street 属性为 null,obj.GetType() 将引发异常。
为什么typeof() 在某些情况下有效,但并非总是如此?即使obj 为空,如何始终获取属性?
【问题讨论】:
-
在对
GetPropertyKeyValue的递归调用中,T绑定到object。GetType和typeof的区别在于typeof(T)为T 的编译时类型提供反射元数据,即object,而GetType提供运行时类型的反射元数据,在你的情况是Address和Street。 -
这能回答你的问题吗? Type Checking: typeof, GetType, or is?
-
typeof 只给出编译时已知的静态值。 TypeOf 为您提供运行时实例类型。它们不一样。您可以依赖 obj.GetType(),因为如果 obj 为 NULL,它首先没有可供您访问的属性。 .当您尝试使用空条件运算符为空时访问它时,您可以轻松防止它爆炸
-
你的
GetPropertyKeyValue不应该是通用的并且使用T,这是参数obj的静态编译时类型。相反,您应该使用GetType。
标签: c#