hBifTs

山自高兮水自深!當塵霧消散,唯事實留傳.荣辱不惊, 看庭前花开花落; 去留随意, 望天上云展云舒.

导航

FormatterServices 好用的东东..

Posted on 2004-05-23 22:19  hbiftsaa  阅读(1883)  评论(7编辑  收藏  举报
在前面一个博客园hush的文章如何不调用构造函数而获得一个类的实例!中,我们知道了使用System.Runtime.Serialization.FormatterServices.GetUninitializedObject可以得到一个没有调用构造函数的对象..

在得到这个对象后,那么如何在不继续调用构造函数的情况下面对其Private成员/其父类的Private成员进行赋值呢??

呵呵,你可能会说,使用Reflection.对,Reflection是可以得到Private Field..
好,给你下面的一个代码.你能否通过Reflection,给Father类中的objFather赋值?
class Father{
      private object objFather;
      public Father( object obj){
                    objFather = obj;
      }
      
       public object GetFather(){
                 return objFather;
       }
}

class Son : Father{
      private object objSon ;
      public Son( object objSon,object objFather) : base(objFather){
             this.objSon = objSon;
      }
}
object obj1 = new object();
object obj2 = new object();
Son x = new Son( obj1,obj2);
Son t = (Son)System.Runtime.Serialization.FormatterServices.GetUninitializedObject( typeof(Son) );
......//你的代码.
t.GetFather() == obj2
即,你通过什么方式让上面的等式成立??



呵呵..
Reflection不行吧..
这里,我们如果要想完成上面的任务,就得使用FormatterServices这个类了~
通过MSDN,我们知道他还有这两个函数 一个,GetObjectData,得到一个Object里的所有的Field的值.
PopulateObjectMembers,给一个Object中的所有的Field赋值..

哈哈.好了,就用这两个函数.
代码如下:
FieldInfo[] fields = typeof( Father).GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
object[] objfields = FormatterServices.GetObjectData(x,fields);
t= FormatterServices.PopulateObjectMembers(t,fields,objfields);


到这里,上面的等式就可以成立了:P


这里面其实是通过Serialize函数来完成的. 所谓的GetObjectData应该就是相当于把这个对象 序列化,这样就可以得到其中的Field的值了.然后再通过反序列化的手段 PopulateObjectMembers(...) 把所得到的数据再放到我们自己的对象中~

JGTM'2004[MVP] 在评论中说了一种方法,是使用Reflection
FieldInfo fatherField = typeof(Father).GetField("objFather", BindingFlags.NonPublic | BindingFlags.Instance);
fatherField.SetValue(t, fatherField.GetValue(x));
..这个方法是成功的..

汗啊...:(
看来得好好学习学习..
不过,我想起来了,当时我是直接 typeof(Son).GetField(...)没得到objFather的FieldInfo.很是不爽(武汉的天太热了),然后就去找FormaterService的东西了...
但是,最后还是使用的typeof(Father).GetField(...)..但是就没想起来可以直接使用Field.SetValue(...)..
:(

呵,还好,学了一招:P
Thx JGTM~