2008-11-19 92 views
30

C#,.NET 3.5你如何找到只有getter和setter的屬性?

我想獲得一個對象的所有屬性,該對象具有一個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. 

編輯:我想知道爲什麼不是工作,以及我應該怎麼做才能得到錯誤。

回答

34

呼叫GetGetMethodGetSetMethod的財產 - 如果這兩個結果都是非空,你在那裏:)

(無參數的版本只返回public方法;還有的用布爾參數的重載指定是否不是你也想要非公開的方法。)

+4

但爲什麼不BindingFlags.SetProperty已經這樣做篩選?這就是我認爲應該做的。 – Matt 2008-11-19 16:32:40

+11

@Matt:因爲BindingFlags.SetProperty和BindingFlags.SetProperty不用於查找,所以在其他情況下使用它們,Get Properties()方法忽略這些標誌。嘗試沒有它們,您將得到相同的結果。請參閱支持的標誌:http://msdn.microsoft.com/en-us/library/kyaxdd3x.aspx – 2008-11-19 16:51:25

1

這不應該工作。

查看msdnGetProperties定義這是允許的:

以下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 in msdn,其中規定:

GetProperty =指定應返回指定屬性 的值。

SetProperty =指定應該設置指定屬性 的值。對於COM屬性,指定此綁定標誌爲 等同於指定PutDispProperty和PutRefDispProperty。

27

怎麼樣......

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

您可以檢查PropertyInfo.CanReadPropertyInfo.CanWrite性能。

0

爲了使它更通用一些,你可以繼承'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); 
        } 
       } 
      } 
     } 
    } 
} 
相關問題