net - reflection c# español
¿Cómo se encuentran solo las propiedades que tienen tanto getter como setter? (5)
C #, .NET 3.5
Estoy tratando de obtener todas las propiedades de un objeto que tenga TANTO un captador como un colocador para la instancia. El código que pensé que debería funcionar es
PropertyInfo[] infos = source.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty | BindingFlags.GetProperty);
Sin embargo, los resultados incluyen una propiedad que no tiene un setter. Para darle una idea simple de mi estructura de herencia que podría estar afectando esto (aunque no sé cómo):
public interface IModel
{
string Name { get; }
}
public class BaseModel<TType> : IModel
{
public virtual string Name { get { return "Foo"; } }
public void ReflectionCopyTo(TType target)
{
PropertyInfo[] infos = this.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty | BindingFlags.GetProperty);
foreach (PropertyInfo info in infos)
info.SetValue(target, info.GetValue(this, null), null);
}
}
public class Child : BaseModel<Child>
{
// I do nothing to override the Name property here
}
Termino con el siguiente error cuando trabajo con Name:
System.ArgumentException: Property set method not found.
EDITAR: Me gustaría saber por qué esto no funciona, así como lo que debería hacer para no obtener el error.
Esto no se supone que funcione.
Vea la definición de GetProperties
en msdn para la cual está permitido:
Los siguientes BindingFlags
filtro BindingFlags
se pueden usar para definir qué tipos anidados incluir en la búsqueda:
* You must specify either BindingFlags.Instance or BindingFlags.Static in order to get a return.
* Specify BindingFlags.Public to include public properties in the search.
* Specify BindingFlags.NonPublic to include non-public properties (that is, private and protected members) in the search.
* Specify BindingFlags.FlattenHierarchy to include static properties up the hierarchy.
O puede ver la definición de GetProperty
/ SetProperty
en msdn , que establece que:
GetProperty = Especifica que se debe devolver el valor de la propiedad especificada.
SetProperty = Especifica que se debe establecer el valor de la propiedad especificada. Para las propiedades COM, especificar este indicador de enlace es equivalente a especificar PutDispProperty y PutRefDispProperty.
Llame a GetGetMethod
y GetSetMethod
en la propiedad: si ambos resultados no son nulos, GetSetMethod
allí :)
(Las versiones sin parámetros solo devuelven métodos públicos; hay una sobrecarga con un parámetro booleano para especificar si desea o no métodos no públicos).
Para hacerlo un poco más genérico, puede heredar de ''ObjectWithDefaultValues'' y / o llamar al método de extensión obj.SetDefaultValues (). Ambos se enumeran a continuación.
Código:
public abstract class ObjectWithDefaultValues : object {
public ObjectWithDefaultValues () : this(true){
}
public ObjectWithDefaultValues (bool setDefaultValues) {
if (setDefaultValues)
this.SetDefaultValues();
}
}
public static class ObjectExtensions {
public static void SetDefaultValues(this object obj) {
foreach (FieldInfo f in obj.GetType().GetFields(BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.SetField)) {
foreach (Attribute attr in f.GetCustomAttributes(true)) {
if (attr is DefaultValueAttribute) {
var dv = (DefaultValueAttribute)attr;
f.SetValue(obj, dv.Value);
}
}
}
foreach (var p in obj.GetType().GetProperties(BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.SetProperty)) {
if (p.GetIndexParameters().Length == 0) {
foreach (Attribute attr in p.GetCustomAttributes(true)) {
if (attr is DefaultValueAttribute) {
var dv = (DefaultValueAttribute)attr;
p.SetValue(obj, dv.Value, null);
}
}
}
}
}
}
Puede verificar las PropertyInfo.CanRead
y PropertyInfo.CanWrite
.
qué tal si...
var qry = typeof(Foo).GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Where(p => p.CanRead && p.CanWrite);