【问题标题】:Why GetProperties() does not return properties when using typeof() but it does when using GetType()?为什么 GetProperties() 在使用 typeof() 时不返回属性,但在使用 GetType() 时却返回?
【发布时间】: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.IdHome.SummaryHome.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 绑定到objectGetTypetypeof 的区别在于typeof(T) 为T 的编译时类型提供反射元数据,即object,而GetType 提供运行时类型的反射元数据,在你的情况是AddressStreet
  • 这能回答你的问题吗? Type Checking: typeof, GetType, or is?
  • typeof 只给出编译时已知的静态值。 TypeOf 为您提供运行时实例类型。它们不一样。您可以依赖 obj.GetType(),因为如果 obj 为 NULL,它首先没有可供您访问的属性。 .当您尝试使用空条件运算符为空时访问它时,您可以轻松防止它爆炸
  • 你的GetPropertyKeyValue 不应该是通用的并且使用T,这是参数obj 的静态编译时类型。相反,您应该使用GetType

标签: c#


【解决方案1】:

类型推断发生在编译时。

也就是说,由于value是静态类型object

object value = property.GetValue(obj, null);

下面一行:

GetPropertyKeyValue(value, key, ref pairs);

编译为

GetPropertyKeyValue<object>(value, key, ref pairs);

typeof(object) 产生......好吧...... object 类型。


如何解决这个问题?传递一个Type 类型的参数,而不是使方法通用。这样,您可以在递归调用中传递property.PropertyType。我建议使用以下签名:

public void GetPropertyKeyValue<T>(T obj, string prefix, List<ExtractedTerm> pairs)
{
    return GetPropertyKeyValue(typeof(T), obj, prefix, pairs);
}

private void GetPropertyKeyValue(Type type, object obj, string prefix, List<ExtractedTerm> pairs)
{
    // contains your logic and recursively calls the non-generic version
    ...
}

【讨论】:

    【解决方案2】:

    试试这个:

    public Dictionary<string, object> GetPropertyKeyValue(string ClassName)
        {
            Dictionary<string, object> Values = new Dictionary<string, object>();
           System.Reflection.PropertyInfo[] Properties = System.Reflection.Assembly.GetExecutingAssembly().GetTypes().First(x => x.Name == ClassName).GetProperties();
    
            foreach (System.Reflection .PropertyInfo property in Properties)
            {
                Values.Add(property.Name, property.GetValue(System.Reflection.Assembly.GetExecutingAssembly().GetTypes().First(x => x.Name == ClassName)));
            }
            return Values;
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-10-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多