2012-04-24 17 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) 'を使用していますか?私は後者がちょうどあなたのbaseclass値を得ると思います。 – Tejs

+0

これはtypeof(BaseClass)を使用できません。これはインターフェイスへの拡張メソッドであるため、実行時にGetType()を使用して基底クラスを決定する必要があります。 – GlenW

+0

拡張メソッドが基本クラスを気にするのはなぜですか?あなたの拡張メソッドが広すぎるように聞こえる。 – Tejs

答えて

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

+0

私が考えることができる唯一の他の方法は、 'GetType()'を検査し、 'Type = BofType'プロパティを'!= typeof(object) 'の間に再帰的に解析し、その参照を使ってそのプロパティを解析します。 – Tejs

+0

はい、そうするだろうが、私はむしろ、より大きな、より複雑なsprocsを書いて、インターフェイスのショートカットを使用しないと思う。それは、私が欲しいものの反対を行うことは簡単ですが、継承されたクラスのプロパティを取得するだけですが、この方法では簡単ではないということはちょっと残念です。 – GlenW

1

基本クラスのプロパティのみに基づいて意思決定を実行する方法が必要なシナリオを見つけました。

だから

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

、これは以下に示すようTypeBaseTypeプロパティを使用して、2つの方法のいずれかで

を行い、その後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

+0

@TheLethalCoder、 –

関連する問題