检查类中是否存在属性


82

我试着知道一个类中是否存在一个属性,我试了一下:

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);
}

4
您介意从中发布相关代码MyClass吗?
nattyddubbs 2013年

Answers:


126

您的方法如下所示:

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

这将扩展添加到所有内容object的基类上。调用此扩展程序时,您将其传递给: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正确地指出,在这一点上你的代码是找物业LabelSystem.Type。该属性不存在。

解决方案是

a)为扩展提供MyClass的实例

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");

2
即您的代码正在寻找Type.Label , not MyClass.Label。
彼得·里奇

怎么把它放在扩展System.Type上?该代码在哪里执行?
Demodave

1
@Demodave-扩展方法只是在公共静态类中。参见此处了解更多信息:msdn.microsoft.com/zh-CN/library/bb383977.aspx
Jamiec 2015年

如果出现此错误:“类型不包含GetProperty的定义”,请阅读以下内容:stackoverflow.com/questions/7858469/…–
Tadej

26

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

如果尝试找出OBJECT(非类)是否具有属性,

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

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

就我而言,我处于ASP.NET MVC局部视图中,并且想要在属性不存在或属性(布尔值)为true时呈现某些内容。

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

帮助我在这里。

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


关于nameof运算符的使用,是否可以工作(不会引发异常)以获取可能不存在的属性的名称?由于原始问题的前提是我们不知道此属性是否存在?
佐伊

您为什么不尝试一下,然后编辑我的答案进行澄清?
Stachu

2

有两种可能性。

你真的没有Label财产。

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

如果您的财产不是公开的,则需要使用BindingFlags.NonPublic或使用其他适合您情况的标志组合。阅读参考的API文档以查找详细信息。

编辑:

哎呀,刚才注意到你打电话GetPropertytypeof(MyClass)typeof(MyClass)Type它肯定没有Label财产。


使用的默认绑定标志是Instance|Public|Staticiirc。
路加福音

@LukeH,我不确定,所以我写了'正确'并添加了'例如':)也许Label是私有财产。
Zdeslav Vojkovic 2013年

1

我收到此错误:绑定接受的答案时,“类型不包含GetProperty的定义”。

这就是我最终得到的:

using System.Reflection;

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

}

0

如果您像我一样绑定:

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

0

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

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

就我而言,我正在遍历表单提交中的属性,如果条目为空,还具有默认值以供使用-所以我需要知道是否存在要使用的值-我在模型中添加了所有默认值的前缀使用Default,所以我需要做的就是检查是否有以此开头的属性。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.