1

リフレクションを使用して、継承されたクラスではなく基本クラスのプロパティのみを取得するにはどうすればよいですか。

基本クラスに仮想メソッドがあり、継承クラスがそれをオーバーライドするとします。オーバーライドが 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;
    }
  }
}

populateSaveParams の foreach ループ内で、Save が呼び出された obj 内のクラスのプロパティを取得する必要があります。継承元のクラスやその子クラスのプロパティは取得しません。

これがより明確になることを願っています。

4

2 に答える 2

1

基本クラスのプロパティのみに基づいて意思決定を行うメソッドが必要なシナリオに遭遇しました。

そのため、インスタンスのプロパティをフィルタリングしました。これは、以下に示す 2 つの方法のいずれかで実行できます。

BaseTypeプロパティを使用してメソッドTypeを呼び出し、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();

以下のコード スニペットは、基本クラスのプロパティを取得し、それらを出力ストリームに書き込みます。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);
        }
    }
}
于 2016-11-25T15:55:51.403 に答える
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

于 2012-04-24T18:35:44.690 に答える