簡體   English   中英

反射無法在抽象類的屬性上找到私有的setter

[英]Reflection can't find private setter on property of abstract class

當我在抽象類中擁有此屬性時:

public IList<Component> Components { get; private set; }

然后當我打電話:

p.GetSetMethod(true)

如果p是指向我的屬性的PropertyInfo對象,則為null。

但是,如果我將屬性setter更改為protected,我可以通過反射看到它。 為什么是這樣? 我似乎沒有回憶起非抽象類的這個問題......

我假設您在抽象類的派生類型的對象上調用它。 該課程根本沒有屬性設定者。 它只位於您的抽象基礎上。 這就是為什么它在您將其標記為protected 獲取屬性設置器時,需要使用抽象類' Type

這是一個老線程,但我最近遇到了類似的問題,上面沒有一個對我有用。 添加我的解決方案,因為它可能對其他人有用。

如前所述,如果屬性的setter是private,則它不存在於繼承的類中。 對我來說DeclaringType的是使用PropertyInfo DeclaringType降低一級

因此,使用setter檢索屬性的代碼如下所示:

var propertyInfo = typeof(MyClass)
    .GetProperty("Components", BindingFlags.NonPublic | BindingFlags.Instance)
    .DeclaringType
    .GetProperty("Components", BindingFlags.NonPublic | BindingFlags.Instance);

在這種情況下, propertyInfo包含SetMethod的值,因此您可以使用反射設置值。

C#Interactive窗口中的一些簡短實驗表明,對於在A類上聲明的屬性P ,以下工作正常:

var p = typeof(A).GetProperty("P").GetSetMethod(true)

但是只要你用A的子類嘗試相同的東西, GetSetMethod就不再解析私有set訪問器:

// class B : A {}
var p = typeof(B).GetProperty("P").GetSetMethod(true) // produces 'null'.

換句話說,當反射類型與屬性的聲明類型相同時,您嘗試的只顯示僅適用於private訪問器。

訣竅是使用BindingFlags枚舉來指定在獲取PropertyInfo對象時希望包含私有成員:

PropertyInfo p = obj.GetType().GetProperty("Components", BindingFlags.NonPublic | BindingFlags.Instance);

建立@piotrwolkowski的工作

var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
var propertyInfo = typeof(MyClass).GetProperty("Components", flags);

// only go to the declaring type if you need to
if (!propertyInfo.CanWrite)
    propertyInfo = propertyInfo.DeclaringType.GetProperty("Components", flags);

我將公共和非公共添加到我的用例的綁定標志(它可能是矯枉過正的,我沒有時間進一步追求它)

我正在設置一個對象的實例,該對象繼承自具有公共get和private set的抽象基礎

再次,所有信用@piotrwolkowski

以下實驗為我揭開了這個問題。 請注意,基類不必是abstract來重現問題。

public class Base
{
    public string Something { get; private set; }
}

public class Derived : Base { }

public class MiscTest
{
    static void Main( string[] args )
    {
        var property1 = typeof( Derived ).GetProperty( "Something" );
        var setter1 = property1.SetMethod; //null
        var property2 = typeof( Base ).GetProperty( "Something" );
        var setter2 = property2.SetMethod; //non-null

        bool test1 = property1 == property2; //false
        bool test2 = property1.DeclaringType == property2.DeclaringType; //true

        var solution = property1.DeclaringType.GetProperty( property1.Name );
        var setter3 = solution.SetMethod; //non-null
        bool test3 = solution == property1; //false
        bool test4 = solution == property2; //true
        bool test5 = setter3 == setter2; //true
    }
}

我從中學到和發現令人驚訝的是,在PropertyInfo上派生類型是不同的實例比PropertyInfo上的基本類型。 奇怪的!

暫無
暫無

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

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