简体   繁体   English

C# - 使用反射设置属性

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

SO Community,所以社区,

So I'm learning C# and am still trying to wrap my head around reflection.所以我正在学习 C# 并且仍在努力思考。 In particular trying to use it to access a property of a property on a class.特别是尝试使用它来访问 class 上的属性。

I've boiled down the basic task that I'm trying to accomplish below:我在下面总结了我要完成的基本任务:

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

        }
    }
}

edit 1 :编辑 1

At Yair Nevet's suggestion I'm grabbing the FieldInfo from the applicable object like,Yair Nevet 的建议下,我从适用的 object 中获取 FieldInfo,例如,

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

But from there I get hung up on accessing and setting the right 'State' Field/Property on that member field但是从那里我挂断了在该成员字段上访问和设置正确的“状态”字段/属性

Solution (ie. here's what I plugged in on that TODO comment):解决方案(即,这是我在该 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;

That does it.就是这样。 Thanks to Shlomi Borovitz for pointing me in the right direction.感谢Shlomi Borovitz为我指明了正确的方向。

Thanks!谢谢!

You are trying to access a Property while the member is actually a private Field : 当成员实际上是私有字段时,您正在尝试访问属性

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

Use GetField method instead for that: 使用GetField方法代替:

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

The FieldInfo object which returned by GetField has property which called FieldInfo , which returns the type of that field. GetField返回的FieldInfo对象具有名为FieldInfo属性,该属性返回该字段的类型。 And you can query it for that type's (the type of the field) properties/fields (and whatever you want) - and get/set them. 您可以查询该类型的(字段的类型)属性/字段(以及您想要的任何内容)-并获取/设置它们。

Remember that both GetType method (of any object), and the FieldInfo.FieldType property return Type object, that you can query in reflection. 请记住,(任何对象的) GetType方法和FieldInfo.FieldType属性都返回Type对象,您可以在反射中进行查询。

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

For each field, you can query the type and for each type, you can query the fields, and get/set them. 对于每个字段,您可以查询类型,对于每种类型,您可以查询字段,并获取/设置它们。

BTW, in C# 4.0 you can use the dynamic pseudo type (it used as a type when declaring dynamic variable, but it's not a real type), and then using that variable, while assuming which properties/fields/methods that variable would have in runtime (ie, using them like they are known in compile time although they don't). 顺便说一句,在C#4.0中,您可以使用dynamic伪类型(在声明动态变量时用作类型,但它不是实型),然后使用该变量,同时假定该变量将具有哪些属性/字段/方法。运行时(即使用它们,就像它们在编译时一样,尽管它们不是)。 This will not work for private members (and I can't warn you enough against calling private members in reflection), but for public members, this would make your code simple and readable, like you never used reflection (although, behind the scenes [in this case] reflection would be used). 这不适用于私有成员(并且我不能警告您不要在反射中调用私有成员),但是对于公共成员,这将使您的代码简单易读,就像您从未使用过反射(尽管在幕后[在这种情况下]将使用反射)。

完成这些步骤...

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.

Given:鉴于:

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

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

The following code uses reflection on a MyClass object to set the int value of PropertyB in PropertyA to NewValue :以下代码使用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