2008-11-19 11 views
30

C#, .NET 3.5Jak znaleźć tylko właściwości, które mają zarówno getter, jak i seter?

Próbuję uzyskać wszystkie właściwości obiektu, które mają ZARÓWNO gettera i setera dla instancji. Kod I myślał powinien pracować jest

PropertyInfo[] infos = source.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty | BindingFlags.GetProperty); 

Jednak wyniki to właściwość, która nie ma setter. Aby dać prosty pomysł mojego struktury dziedziczenia, które mogą mieć wpływ na to (choć nie wiem jak):

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 
} 

I skończyć z powodu następującego błędu podczas pracy z nazwa:

System.ArgumentException: Property set method not found. 

EDYCJA: Chciałbym wiedzieć, dlaczego to działa nie, a także, co powinienem zrobić, aby nie dostać błąd.

Odpowiedz

34

GetGetMethod połączeń i GetSetMethod na nieruchomości - jeśli oba wyniki są niezerowe, jesteś tam :)

(wersje bez parametrów wrócić tylko metody publiczne; tam przeciążenia z logiczną parametru, aby określić, czy nie chcesz także metod niepublicznych.)

+4

Ale dlaczego nie robi BindingFlags.SetProperty już robi, że filtrowanie? Tak właśnie myślałem. – Matt

+11

@Matt: Ponieważ BindingFlags.SetProperty i BindingFlags.SetProperty nie są używane do wyszukiwania, są one używane w innych okolicznościach, metoda Get Properties() ignoruje te flagi. Wypróbuj bez nich, uzyskasz ten sam wynik.Zobacz obsługiwane flagi: http://msdn.microsoft.com/en-us/library/kyaxdd3x.aspx –

1

To nie powinno działać.

Zobacz definicję GetProperties na msdn dla którego jest dozwolone: ​​

Poniższe BindingFlags flagi filtry mogą być używane do określenia, które zagnieżdżone typy uwzględnić w wyszukiwaniu:

* 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. 

Albo można zobaczyć definicja GetProperty/SetProperty w msdn, która stwierdza, że:

GetProperty = Określa, że ​​wartość określonej właściwości powinna zostać zwrócona.

SetProperty = Określa, że ​​należy ustawić wartość określonej właściwości . W przypadku właściwości COM określenie tej flagi wiążącej to równoważne określeniu PutDispProperty i PutRefDispProperty.

27

jak o ...

var qry = typeof(Foo).GetProperties(BindingFlags.Instance | BindingFlags.Public) 
      .Where(p => p.CanRead && p.CanWrite); 
32

Można sprawdzić PropertyInfo.CanRead i PropertyInfo.CanWrite właściwości.

+2

Pamiętaj jednak, że zwrócą "true", nawet jeśli pobierają/seter nie jest 'publiczne'. Te właściwości po prostu sprawdzają istnienie getter/setter. –

0

Aby było to trochę bardziej ogólne, można dziedziczyć po ObjectWithDefaultValues ​​i/lub wywołać metodę rozszerzenia obj.SetDefaultValues ​​(). Oba są wymienione poniżej.

Kod:

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); 
        } 
       } 
      } 
     } 
    } 
} 
Powiązane problemy