【问题标题】:Check if a property exists in a class检查类中是否存在属性
【发布时间】:2013-03-11 14:26:19
【问题描述】:

我想知道一个属性是否存在于一个类中,我试过这个:

public static bool HasProperty(this object obj, string propertyName)
{
    return obj.GetType().GetProperty(propertyName) != null;
}

不明白为什么第一个测试方法不通过?

[TestMethod]
public void Test_HasProperty_True()
{
    var res = typeof(MyClass).HasProperty("Label");
    Assert.IsTrue(res);
}

[TestMethod]
public void Test_HasProperty_False()
{
    var res = typeof(MyClass).HasProperty("Lab");
    Assert.IsFalse(res);
}

【问题讨论】:

  • 您介意从MyClass发布相关代码吗?

标签: c# .net reflection


【解决方案1】:

您的方法如下所示:

public static bool HasProperty(this object obj, string propertyName)
{
    return obj.GetType().GetProperty(propertyName) != null;
}

这会在object 上添加一个扩展 - everything 的基类。当您调用此扩展程序时,您将其传递给 Type:

var res = typeof(MyClass).HasProperty("Label");

您的方法需要一个类的实例,而不是Type。否则你实际上是在做

typeof(MyClass) - this gives an instanceof `System.Type`. 

然后

type.GetType() - this gives `System.Type`
Getproperty('xxx') - whatever you provide as xxx is unlikely to be on `System.Type`

正如@PeterRitchie 正确指出的那样,此时您的代码正在System.Type 上寻找属性Label。该属性不存在。

解决办法是

a) 为扩展提供一个 MyClass 的instance

var myInstance = new MyClass()
myInstance.HasProperty("Label")

b) 将扩展名放在System.Type

public static bool HasProperty(this Type obj, string propertyName)
{
    return obj.GetProperty(propertyName) != null;
}

typeof(MyClass).HasProperty("Label");

【讨论】:

  • 即您的代码正在寻找`Type.Label, not MyClass.Label`。
  • 如何将它放在扩展 System.Type 上,在哪里可以找到/。这段代码在哪里执行?
  • @Demodave - 扩展方法只是在一个公共静态类中。请参阅此处了解更多信息:msdn.microsoft.com/en-GB/library/bb383977.aspx
  • 如果您收到此错误:“类型不包含 GetProperty 的定义”,请阅读:stackoverflow.com/questions/7858469/…
【解决方案2】:

这回答了一个不同的问题:

如果试图确定一个 OBJECT(不是类)是否有属性,

OBJECT.GetType().GetProperty("PROPERTY") != null

如果(但不仅是)该属性存在,则返回 true。

在我的例子中,我在一个 ASP.NET MVC 部分视图中,如果属性不存在或者属性(布尔值)为真,我想渲染一些东西。

@if ((Model.GetType().GetProperty("AddTimeoffBlackouts") == null) ||
        Model.AddTimeoffBlackouts)

在这里帮助了我。

编辑:如今,使用 nameof 运算符而不是字符串化的属性名称可能很聪明。

【讨论】:

  • 关于nameof运算符的使用,是否可以(不抛出异常)获取可能不存在的属性名称?由于原始问题的前提是我们不知道该属性是否存在?
  • 您为什么不尝试一下,然后编辑我的答案以澄清?
【解决方案3】:

在绑定已接受的答案时出现此错误:“类型不包含 GetProperty 的定义”。

这就是我最终的结果:

using System.Reflection;

if (productModel.GetType().GetTypeInfo().GetDeclaredProperty(propertyName) != null)
{

}

【讨论】:

    【解决方案4】:

    有两种可能。

    你真的没有Label属性。

    您需要调用适当的GetProperty overload 并传递正确的绑定标志,例如BindingFlags.Public | BindingFlags.Instance

    如果您的属性不是公开的,您将需要使用BindingFlags.NonPublic 或其他适合您的用例的标志组合。阅读引用的 API 文档以查找详细信息。

    编辑:

    糟糕,刚刚注意到您在 typeof(MyClass) 上拨打了 GetPropertytypeof(MyClass)Type 肯定没有 Label 属性。

    【讨论】:

    • 使用的默认绑定标志是Instance|Public|Static, iirc。
    • @LukeH,我不确定,所以我写了“正确”并添加了“例如”:) 也许Label 是私有财产。
    【解决方案5】:

    如果你像我一样有约束力:

    <%# Container.DataItem.GetType().GetProperty("Property1") != null ? DataBinder.Eval(Container.DataItem, "Property1") : DataBinder.Eval(Container.DataItem, "Property2")  %>
    

    【讨论】:

      【解决方案6】:

      我不确定为什么需要这样做的上下文,因此这可能无法为您返回足够的信息,但这是我能够做到的:

      if(typeof(ModelName).GetProperty("Name of Property") != null)
      {
      //whatevver you were wanting to do.
      }
      

      在我的情况下,我正在处理表单提交中的属性,并且如果条目留空,则还有要使用的默认值 - 所以我需要知道是否有要使用的值 - 我为所有默认值添加了前缀在具有 Default 的模型中,所以我需要做的就是检查是否有一个以它开头的属性。

      【讨论】:

        猜你喜欢
        • 2012-08-16
        • 1970-01-01
        • 2011-02-01
        • 2021-04-22
        • 1970-01-01
        • 2018-02-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多