簡體   English   中英

C#反射來自通用基類中的字段的GetValue

[英]C# reflection GetValue from a field in generic base class

問題是我們不能得到只存在於具有泛型類型的基類的字段(非泛型)的GetValue。 請參閱下面的代碼段。 調用

f.GetValue(a)

將拋出帶有消息的異常:無法對Type.ContainsGenericParameters為true的類型的字段執行后期綁定操作。

class Program
{
    static void Main(string[] args)
    {
        Type abstractGenericType = typeof (ClassB<>);
        FieldInfo[] fieldInfos =
            abstractGenericType.GetFields(BindingFlags.Public |  BindingFlags.Instance);

        ClassA a = new ClassA("hello");
        foreach(FieldInfo f in fieldInfos)
        {
            f.GetValue(a);// throws InvalidOperationhException 
        }
    }
}

internal class ClassB<T>
{
    public string str;
    public ClassB(string s)
    {
        str = s;
    }
}

internal class ClassA : ClassB<String>
{
    public ClassA(string value) : base(value)
    {}
}

我們的設計要求我們在擁有實際對象的任何實例之前首先獲得FieldInfo。 所以我們不能使用

Type typeA = abstractGenericType.MakeGenericType(typeof(string));
FieldInfo[] fieldInfos = typeA.GetFields();

謝謝

我想這個問題來自於通用類是使用特定類型動態編譯的。 泛型類型也可以定義為

internal class ClassB<T>
{
    public T value;

    public string str;
    public ClassB(string s)
    {
        str = s;
    }
}

那么你在獲取字段“值”的值時會遇到問題。 變通辦法將使用.GetType()直接檢索類型,或創建一個沒有包含您要訪問的字段的泛型參數的新基類。

如果您靈活並且願意使用屬性而不是字段,則可以通過在泛型基類上放置非泛型接口來完成您想要的操作。 這是原始代碼的重新分解版本,顯示了變化和概念。

    class Program
    {
        public static void Main(string[] args)
        {
            Type interfaceType = typeof(IGetStr);
            PropertyInfo[] propertyInfos = interfaceType.GetProperties(BindingFlags.Public | BindingFlags.Instance);

            ClassA a = new ClassA("hello");

            foreach (PropertyInfo p in propertyInfos)
            {
                var myValue = p.GetValue(a, null); // does not throw InvalidOperationException 
            }
        }
    }

    internal interface IGetStr
    {
        string StringValue { get; set; }
    }

    internal class ClassB<T> : IGetStr
    {
        public string str;

        public ClassB(string s)
        {
            str = s;
        }

        public string StringValue
        {
            get
            {
                return str;
            }
            set
            {
                str = value;
            }
        }
    }

    internal class ClassA : ClassB<String>
    {
        public ClassA(string value)
            : base(value)
        { }
    }

接口是訪問泛型類的非泛型屬性的好方法。 使用如圖所示的接口,只要使用IGetStr的接口,就可以獲得任何繼承自ClassB <>的類的名為“StringValue”的屬性,而不管泛型類型如何。

您也可以將“ClassA”對象轉換為IGetStr,以下內容將起作用。 (非常適合所有從您的通用基礎繼承的項目列表)

var result = ((IGetStr)a).StringValue;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM