Compruebe si existe una propiedad en una clase

82

Intento saber si existe una propiedad en una clase, probé esto:

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

No entiendo por qué no pasa el primer método de prueba.

[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);
}
Kris-I
fuente
4
¿Le importaría publicar el código relevante de MyClass?
nattyddubbs

Respuestas:

126

Tu método se ve así:

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

Esto agrega una extensión a objectla clase base de todo . Cuando llama a esta extensión, le está pasando un Type:

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

Su método espera una instancia de una clase, no un Type. De lo contrario, esencialmente estás haciendo

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

Entonces

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

Como @PeterRitchie señala correctamente, en este punto su código está buscando una propiedad Labelen System.Type. Esa propiedad no existe.

La solución es

a) Proporcione una instancia de MyClass a la extensión:

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

b) Pon la extensión en System.Type

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

y

typeof(MyClass).HasProperty("Label");
Jamiec
fuente
2
es decir, su código está buscando` Type.Label , not MyClass.Label`.
Peter Ritchie
¿Cómo se pondría esto en la extensión System? Escriba dónde se encuentra /. ¿A dónde va esto en el código para ejecutar?
Demodave
1
@Demodave: los métodos de extensión solo están en una clase estática pública. Consulte aquí para obtener más información: msdn.microsoft.com/en-GB/library/bb383977.aspx
Jamiec
Si recibe este error: "El tipo no contiene una definición para GetProperty", lea esto: stackoverflow.com/questions/7858469/…
Tadej
26

Esto responde a una pregunta diferente:

Si está tratando de averiguar si un OBJETO (no una clase) tiene una propiedad,

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

devuelve verdadero si (pero no solo si) la propiedad existe.

En mi caso, estaba en una vista parcial ASP.NET MVC y quería renderizar algo si la propiedad no existía o la propiedad (booleana) era verdadera.

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

me ayudó aquí.

Editar: hoy en día, probablemente sea inteligente usar el nameofoperador en lugar del nombre de propiedad en cadena.

Stachu
fuente
Con respecto al uso del nameofoperador, ¿funcionará (sin lanzar una excepción) para obtener el nombre de una propiedad que puede no existir? ¿Dado que la premisa de la pregunta original era que no sabemos si existe esta propiedad?
Zoe
¿Por qué no lo intentas y luego editas mi respuesta para aclarar?
Stachu
2

Hay 2 posibilidades.

Realmente no tienes Labelpropiedad.

Debe llamar a la sobrecarga de GetProperty apropiada y pasar las banderas de enlace correctas, por ejemploBindingFlags.Public | BindingFlags.Instance

Si su propiedad no es pública, deberá usar BindingFlags.NonPublico alguna otra combinación de indicadores que se adapte a su caso de uso. Lea los documentos de la API a los que se hace referencia para encontrar los detalles.

EDITAR:

Lamentablemente, solo se dio cuenta de que llame GetPropertya typeof(MyClass). typeof(MyClass)es el Typeque seguro no tiene Labelpropiedad.

Zdeslav Vojkovic
fuente
Los indicadores de enlace predeterminados que se utilizan son Instance|Public|Staticiirc.
LukeH
@LukeH, no estaba seguro, así que escribí 'correcto' y agregué 'eg' :) tal vez Labelsea ​​propiedad privada.
Zdeslav Vojkovic
1

Recibí este error: "El tipo no contiene una definición para GetProperty" al vincular la respuesta aceptada.

Esto es con lo que terminé:

using System.Reflection;

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

}
Tadej
fuente
0

Si estás vinculante como yo:

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

No estoy seguro del contexto de por qué era necesario, por lo que es posible que esto no le devuelva suficiente información, pero esto es lo que pude hacer:

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

En mi caso, estoy revisando las propiedades de un envío de formulario y también tengo valores predeterminados para usar si la entrada se deja en blanco, por lo que necesitaba saber si había un valor para usar, prefijé todos mis valores predeterminados en el modelo con Default, así que todo lo que tenía que hacer era verificar si había una propiedad que comenzara con eso.

C Gil
fuente