Как вы находите только свойства, которые имеют как геттер, так и сеттер?
С#,.NET 3.5
Я пытаюсь получить все свойства объекта, у которого есть BOTH getter и setter для экземпляра. Код, который, как я думал, должен работать,
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.
EDIT: Я хотел бы знать, почему это не работает, а также то, что я должен делать, чтобы не получить ошибку.
Ответы
Ответ 1
Вызвать GetGetMethod
и GetSetMethod
на свойство - если оба результата не равны нулю, вы там:)
(Безпараметрические версии возвращают только общедоступные методы, там перегрузка с логическим параметром указывает, хотите ли вы также непубличные методы.)
Ответ 2
Вы можете проверить свойства PropertyInfo.CanRead
и PropertyInfo.CanWrite
.
Ответ 3
как насчет...
var qry = typeof(Foo).GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Where(p => p.CanRead && p.CanWrite);
Ответ 4
Это не должно работать.
См. определение 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.
Ответ 5
Чтобы сделать его более универсальным, вы можете наследовать от 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);
}
}
}
}
}
}