Как вы находите только свойства, которые имеют как геттер, так и сеттер? - PullRequest
31 голосов
/ 19 ноября 2008

C #, .NET 3.5

Я пытаюсь получить все свойства объекта, которые имеют ОБА как геттер, так и сеттер для экземпляра. Код, который я думал должен работать, это

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

Однако результаты включают свойство, которое не имеет установщика. Чтобы дать вам простое представление о моей структуре наследования, которая может повлиять на это (хотя я не знаю как):

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
}

Я получаю следующую ошибку при работе с именем:

System.ArgumentException: Property set method not found.

РЕДАКТИРОВАТЬ: Я хотел бы знать, почему это не работает, а также то, что я должен делать, чтобы не получить ошибку.

Ответы [ 5 ]

37 голосов
/ 19 ноября 2008

Звоните GetGetMethod и GetSetMethod на имущество - если оба результата не являются нулевыми, вы там:)

(Версии без параметров возвращают только общедоступные методы; существует перегрузка с логическим параметром, указывающим, хотите ли вы также закрытые методы.)

32 голосов
/ 22 июля 2010

Вы можете проверить свойства PropertyInfo.CanRead и PropertyInfo.CanWrite.

28 голосов
/ 02 января 2009

как насчет ...

var qry = typeof(Foo).GetProperties(BindingFlags.Instance | BindingFlags.Public)
            .Where(p => p.CanRead && p.CanWrite);
1 голос
/ 19 ноября 2008

Это не должно работать.

См. Определение GetProperties в msdn , для которого разрешено:

Следующие BindingFlags флаги фильтра могут использоваться для определения того, какие вложенные типы следует включить в поиск:

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

Или вы можете увидеть определение GetProperty / SetProperty в msdn , в котором говорится:

GetProperty = Указывает, что значение указанного свойства должен быть возвращен.

SetProperty = Указывает, что значение указанного свойства должен быть установлен. Для свойств COM указание этого флага привязки эквивалентно указанию PutDispProperty и PutRefDispProperty.

0 голосов
/ 08 февраля 2013

Чтобы сделать его немного более универсальным, вы можете наследовать от ObjectWithDefaultValues ​​и / или вызвать метод расширения obj.SetDefaultValues ​​(). Оба перечислены ниже.

Код:

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);
                    }
                }
            }
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...