簡體   English   中英

C# - 使用反射設置屬性

[英]C# - Set Property of a Property with Reflection

所以社區,

所以我正在學習 C# 並且仍在努力思考。 特別是嘗試使用它來訪問 class 上的屬性。

我在下面總結了我要完成的基本任務:

public enum SIGNAL_STATE { NOT_RETRIEVED = 0, RETRIEVING = 1, RETRIEVED = 2, FAILED = 3 }

public class MyObjectClass
{
    public string MyString;
    private SIGNAL_STATE _state = SIGNAL_STATE.NOT_RETRIEVED;
    public SIGNAL_STATE State { get { return _state; } set { _state = value;} }
}

public class NeedToReflect
{
    private MyObjectClass _myObject1 = new MyObjectClass();
    private MyObjectClass _myObject2 = new MyObjectClass();
    private MyObjectClass _myObject3 = new MyObjectClass();

    public MyObjectClass MyObject1
    {
        get{return _myObject1;} 
        set{_myObject1 = value;}
    }

    public MyObjectClass MyObject2
    {
        get{return _myObject2;}
        set{_myObject2 = value;}
    }

    public MyObjectClass MyObject3
    {
        get{return _myObject3;}
        set{_myObject3 = value;}
    }

    public static void Main(string [] args){
        NeedToReflect needToReflect = new NeedToReflect();

        string fieldName;
        for(int idx = 1; idx<=3; ++idx)
        {
            fieldName = String.Format("MyObject{0}",idx);

            //TODO: set state of 'MyObject' values to SIGNAL_STATE.RETRIEVING

        }
    }
}

編輯 1

Yair Nevet 的建議下,我從適用的 object 中獲取 FieldInfo,例如,

FieldInfo fieldInfo = needToReflect.GetType().GetField(fieldName, BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.Instance);

但是從那里我掛斷了在該成員字段上訪問和設置正確的“狀態”字段/屬性

解決方案(即,這是我在該 TODO 評論中插入的內容):

// Determine what binding flags will give us proper access to our member field
BindingFlags bindFlags = BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.Instance;
// Get the field for that field
FieldInfo fieldInfo = needToReflect.GetType().GetField(fieldName, bindFlags);
// Pass in the containing object that we're reflecting on to get an instance of the member field
MyObjectClass myField = (MyObjectClass) fieldInfo.GetValue(needToReflect);
// We can now directly access and edit the value in question
myField.State = SIGNAL_STATE.RETRIEVING;

就是這樣。 感謝Shlomi Borovitz為我指明了正確的方向。

謝謝!

當成員實際上是私有字段時,您正在嘗試訪問屬性

propertyName = String.Format("MyObject{0}",idx);

使用GetField方法代替:

needToReflect.GetType().GetField(propertyName, BindingFlags.NonPublic |BindingFlags.GetField | BindingFlags.Instance);

GetField返回的FieldInfo對象具有名為FieldInfo屬性,該屬性返回該字段的類型。 您可以查詢該類型的(字段的類型)屬性/字段(以及您想要的任何內容)-並獲取/設置它們。

請記住,(任何對象的) GetType方法和FieldInfo.FieldType屬性都返回Type對象,您可以在反射中進行查詢。

object obj =... 
var field = obj.GetType().GetField(fieldName,...);
field.FieldType.GetField(... 
//etc... etc... 

對於每個字段,您可以查詢類型,對於每種類型,您可以查詢字段,並獲取/設置它們。

順便說一句,在C#4.0中,您可以使用dynamic偽類型(在聲明動態變量時用作類型,但它不是實型),然后使用該變量,同時假定該變量將具有哪些屬性/字段/方法。運行時(即使用它們,就像它們在編譯時一樣,盡管它們不是)。 這不適用於私有成員(並且我不能警告您不要在反射中調用私有成員),但是對於公共成員,這將使您的代碼簡單易讀,就像您從未使用過反射(盡管在幕后[在這種情況下]將使用反射)。

完成這些步驟...

1) Get the Type.
2) Have an instance of that type.
3) Get the PropertyInfo for the property.
4) Call "GetSetMethod" on the PropertyInfo object. It will return a MethodInfo object.
5) Invoke the MethodInfo object using the instance of the type and a value.

鑒於:

class ClassyMcClass
{
    public int PropertyB { get; set; }
}

class MyClass
{
    public ClassyMcClass PropertyA { get; set; }
}

以下代碼使用MyClass object 上的反射將PropertyBPropertyA的 int 值設置為NewValue

PropertyInfo propA = typeof(MyClass).GetProperty("PropertyA");
PropertyInfo probBofA = propA.PropertyType.GetProperty("PropertyB");

// Set property B of property A, where obj is of type MyClass
probBofA.SetValue(propA.GetValue(obj), NewValue, null);

暫無
暫無

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

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