场参考和反射

时间:2014-01-23 20:12:15

标签: c# reflection

一个班级有一个领域。第二类应该能够引用该字段并进行更改。由于你不能在内存中获取字段的地址,我必须使用反射。但我的方法只适用于非封装字段。所以基本上:

这有效:

public class Dummy
{
    public int field;
    public Dummy(int value)
    {
        this.field = value;
    }
}

class Program
{
    public static void Main()
    {
        Dummy d = new Dummy(20);
        //Shows 20
        Console.WriteLine(d.field.ToString());
        d.GetType().GetField("field", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).SetValue(d, 40);
        //It should show 40 now
        Console.WriteLine(d.field.ToString());
    }
}

这不会(抛出NullReferenceException):

public class Dummy
{
    public int field { get; set; }
    public Dummy(int value)
    {
        this.field = value;
    }
}

class Program
{
    public static void Main()
    {
        Dummy d = new Dummy(20);
        //Shows 20
        Console.WriteLine(d.field.ToString());
        d.GetType().GetField("field", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).SetValue(d, 40);
        //It should show 40 now
        Console.WriteLine(d.field.ToString());
    }
}

为什么呢?我如何解决它?我甚至可以访问这样的封装对象吗?谢谢!

3 个答案:

答案 0 :(得分:2)

它不再是一个领域。您应该使用GetProperty方法代替GetField:

d.GetType().GetProperty(...);

答案 1 :(得分:2)

在这两种情况下,你都可以(而且应该)写

d.field = 40;

如果您希望字段为非私有字段,则should always会将其设为属性,如第二个示例所示。你永远不应该有公共领域。请注意,如果您需要通过反思访问媒体资源,则需使用GetProperty,而不是GetField

答案 2 :(得分:0)

您能更准确地了解用例吗? 也许一个隔离属性访问器的接口更好:

public interface IDummy
{
    int field { get; set; }
}

您将能够在不了解对象其余部分的情况下操纵该属性。当你想“引用”一个字段时,这不是你需要的吗?