2012-04-24 79 views
0

如何使用反射來僅獲取基類中的屬性,而不是繼承的類。只使用反射獲得基類屬性,而不是繼承類

說我的基類有一個虛擬方法,並且繼承類覆蓋它。如果覆蓋調用base.MyMethod(),則base.MyMethod()中的反射將從兩個類或僅繼承類獲取屬性,具體取決於使用BindingFlags。

有沒有辦法只能訪問基類中的屬性?

編輯:也許有些代碼可以解釋爲什麼我想這樣做。

internal static void Save(DataTransactionAccess data, string sproc, object obj) 
{ 
    if (checkMandatoryProperties(obj)) 
    { 
    saveToDatabase(data, sproc, obj); 
    } 
} 

private static void saveToDatabase(DataTransactionAccess data, string sproc, object obj) 
{ 
    List<object> paramList; 
    PropertyInfo idProperty; 
    populateSaveParams(out paramList, out idProperty, obj); 
    if (idProperty != null) 
    { 
    int id = data.ExecuteINTProcedure(sproc, paramList.ToArray()); 
    idProperty.SetValue(obj, id, null); 
    } 
    else 
    { 
    data.ExecuteProcedure(sproc, paramList.ToArray()); 
    } 
} 

private static void populateSaveParams(out List<object> paramList, out PropertyInfo idProperty, object obj) 
{ 
    paramList = new List<object>(); 
    idProperty = null; 
    foreach (PropertyInfo info in obj.GetType().GetProperties()) 
    { 
    if (info.GetCustomAttributes(typeof(SaveProperty), true).Length > 0) 
    { 
     paramList.Add("@" + info.Name); 
     paramList.Add(info.GetValue(obj, null)); 
    } 
    if (info.GetCustomAttributes(typeof(SaveReturnIDProperty), true).Length > 0) 
    { 
     idProperty = info; 
    } 
    } 
} 

這是我需要獲得OBJ內的類保存了調用,而不是從繼承或任何其子類的任何類的屬性populateSaveParams foreach循環中。

希望這可以讓它更清晰。

+2

你在使用'GetType'或'typeof(BaseClass)'檢查它的值時?我認爲後者只會得到你的基類值。 – Tejs 2012-04-24 18:07:15

+0

我不能使用typeof(BaseClass),因爲這是針對接口的擴展方法,所以需要在運行時使用GetType()來確定基礎類。 – GlenW 2012-04-24 18:16:27

+0

爲什麼你的擴展方法關心基類,然後如果它只知道接口?聽起來你的擴展方法太寬泛了。 – Tejs 2012-04-24 18:17:38

回答

0

這聽起來對我來說就像一點點重組一樣。任何實現該接口將返回一組保存操作:

public interface ISomeInterface 
{ 
    IEnumerable<SaveStep> SaveData(); 
} 

public class SomeClass : SomeBaseClass, ISomeInterface 
{ 
    public virtual IEnumerable<SaveStep> SaveData() 
    { 
     foreach(var item in base.SaveData()) 
      yield return item; 

     yield return new SaveStep { ... } 
    } 
} 

然後你擴展方法(或任何調用真的)只需要調用SaveData方法,以及你回來一套SaveStep對象,你可以用它來的使用基於類所需的任何數據構建過程調用。

+0

感謝您的建議,我會考慮將來的工作。但是,我仍然想知道如何實現我在原始問題中提出的問題。 – GlenW 2012-04-24 18:47:08

+0

我唯一能想到的方法就是檢查'GetType()'並遞歸地解析'Type.BaseType'屬性,而它是'!= typeof(object)',然後使用該引用來解析它的屬性。 – Tejs 2012-04-24 18:50:33

+0

是的,這樣做,但我想我寧願寫更大,更復雜的sprocs,不使用界面捷徑。看起來有點愚蠢,它直接做我想做的事的對立面,只得到繼承類的屬性,但這樣做並不容易。 – GlenW 2012-04-24 18:56:41

1

我遇到了一個場景,我只需要一個基於類的屬性來執行決策的方法。

所以我過濾的情況下這可以通過以下兩種方式之一來完成,如下圖所示的屬性,

Type使用BaseType屬性,然後調用GetProperties方法,

var baseType = instance.GetType().BaseType; 
var properties = baseType.GetProperties(); 

使用DeclaringType屬性檢查它是來自基類還是派生類,

var type = instance.GetType(); 
var properties = type.GetProperties(); 
// properties = properties.Where(p => p.DeclaringType.FullName == typeof(SomeClass).FullName).ToArray(); 
properties = properties.Where(p => p.DeclaringType.FullName == type.BaseType.FullName).ToArray(); 

下面的代碼片段檢索基類屬性並將它們寫入輸出流。 Here是編譯C#在線鏈接

using System; 
using System.Linq; 

namespace Rextester 
{ 
    public class Program 
    { 
     public static void Main(string[] args) 
     { 
      // Employee (derived class) - Person (base class) 
      var employee = new Employee 
      { 
       Company = "Stack Overflow", 
       Designation = "Community Manager", 
       FirstName = "Josh", 
       LastName = "Heyer" 
      }; 

      var baseType = employee.GetType().BaseType; 
      var properties = baseType.GetProperties(); 
      var method = baseType.GetMethod("Print"); 

      for (var i = 0; i < properties.Count(); i++) 
      { 
       Console.WriteLine(properties[i].Name); 
      } 

      Console.WriteLine(); 
      method.Invoke(employee, null); 
     } 
    } 

    public class Person 
    { 
     public string FirstName { get; set; } 

     public string LastName { get; set; } 

     public virtual void Print() 
     { 
      Console.WriteLine("Name: {0} {1}", FirstName, LastName); 
     } 
    } 

    public class Employee : Person 
    { 
     public string Company { get; set; } 

     public string Designation { get; set; } 

     public override void Print() 
     { 
      base.Print(); 
      Console.WriteLine("Employment Details: {0} {1}", Company, Designation); 
     } 
    } 
} 
+1

考慮發佈一個修訂後的答案,目前它看起來像一個代碼轉儲,我懷疑任何人有時間篩選它以查找相關信息 – TheLethalCoder 2016-11-25 15:59:42

+0

@TheLethalCoder,感謝您的建議,我已經更新了我的答案 – 2016-11-25 17:54:29