C# 您如何仅找到同时具有 getter 和 setter 的属性?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/302476/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do you find only properties that have both a getter and setter?
提问by Matt
C#, .NET 3.5
C#、.NET 3.5
I am trying to get all of the properties of an object that have BOTH a getter and a setter for the instance. The code I thoughtshould work is
我正在尝试获取一个对象的所有属性,这些属性同时具有实例的 getter 和 setter。我认为应该工作的代码是
PropertyInfo[] infos = source.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty | BindingFlags.GetProperty);
However, the results include a property that does not have a setter. To give you a simple idea of my inheritance structure that might be affecting this (though I don't know how):
但是,结果包括一个没有 setter 的属性。为了让您对我的可能会影响此的继承结构有一个简单的了解(尽管我不知道如何):
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 end up with the following error when working with Name:
使用 Name 时,我最终遇到以下错误:
System.ArgumentException: Property set method not found.
EDIT: I would like to know why this does notwork, as well as what I should be doing to not get the error.
编辑:我想知道为什么这样做没有工作,还有什么我应该怎样做才能不出现错误。
采纳答案by Jon Skeet
Call GetGetMethod
and GetSetMethod
on the property - if both results are non-null, you're there :)
调用GetGetMethod
和GetSetMethod
属性 - 如果两个结果都不为空,你就在那里:)
(The parameterless versions only return public methods; there's an overload with a boolean parameter to specify whether or not you also want non-public methods.)
(无参数版本只返回公共方法;有一个带有布尔参数的重载来指定您是否还需要非公共方法。)
回答by Jon Skeet
This isn't supposed to work.
这不应该工作。
See definition of GetProperties
on msdnfor which is allowed:
见的定义GetProperties
在MSDN对允许:
The following BindingFlags
filter flags can be used to define which nested types to include in the search:
以下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.
Or you can see the definition of GetProperty
/SetProperty
in msdn, which states that:
或者您可以在msdn 中看到GetProperty
/的定义,其中指出:SetProperty
GetProperty = Specifies that the value of the specified property should be returned.
SetProperty = Specifies that the value of the specified property should be set. For COM properties, specifying this binding flag is equivalent to specifying PutDispProperty and PutRefDispProperty.
GetProperty = 指定应返回指定属性的值。
SetProperty = 指定应设置指定属性的值。对于 COM 属性,指定此绑定标志等效于指定 PutDispProperty 和 PutRefDispProperty。
回答by Tim Jarvis
how about...
怎么样...
var qry = typeof(Foo).GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Where(p => p.CanRead && p.CanWrite);
回答by Matthieu DUFOURNEAUD-RAVEL
You can check the PropertyInfo.CanRead
and PropertyInfo.CanWrite
properties.
您可以检查PropertyInfo.CanRead
和PropertyInfo.CanWrite
属性。
回答by Herman Schoenfeld
To make it a little more generic you can inherit from 'ObjectWithDefaultValues' and/or call obj.SetDefaultValues() extension method. Both are listed below.
为了使它更通用一点,您可以从 'ObjectWithDefaultValues' 继承和/或调用 obj.SetDefaultValues() 扩展方法。下面列出了两者。
Code:
代码:
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);
}
}
}
}
}
}