2014-01-23 55 views
0

一个类有一个字段。第二类应该能够引用该字段并对其进行更改。由于您无法获取内存中的字段地址,因此我必须使用反射。但是我的方法只适用于非封装字段。所以基本上:字段参考和反思

这工作:

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()); 
    } 
} 

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

+2

在你的第二个例子中,这不是'field',它是一个'property'。 – EkoostikMartin

+2

为什么你需要在这里反思? 'field'和'property'都是公开的,所以'd.field = 40;'... – Alden

+0

这只是一个愚蠢的例子。你显然不需要在这里反思。 – JTaylor

回答

2

它不再是一个领域。相反,getfield命令的,你应该使用GetProperty方法:

d.GetType().GetProperty(...); 
+0

这(当然)的作品!非常感谢你! :) – JTaylor

2

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

d.field = 40; 

如果你想有一个领域是非私有的,你should always使它财产,如你的第二个例子。你永远不应该有公共领域。请注意,如果您需要通过反射访问某个媒体资源,则可以使用GetProperty而不是GetField

+0

感谢您提供一些有价值的信息。 :) – JTaylor

0

您能更精确地了解用例吗? 也许这隔离特性存取的接口比较好:

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

您可以操纵性能,无需了解对象的其余任何事情。当你想“引用”单个字段时,这不是你需要的吗?

+0

你肯定是对的,但在我的情况下,有太多种使用接口。我只想要一个拥有对象引用的类,当它改变时 - 它会在其他地方更改字段/属性。那上面的东西只是一个愚蠢的例子,要清楚看看错误在哪里。 – JTaylor

+0

完美。我想你会查询价值。毋庸置疑,setters +事件对于这些情况非常有用。我觉得你没有访问源代码,无法绕过投票... – pid