在Teddy的 DynamicMethodProxyFactory组件中,提供了一种调用非公有方法的机制。本质上,通过这个组件是可以实现任意的公有和非公有属性的读写操作(属性本质上可以通过它的get/set方法以方法的形式访问)。而且性能会比反射提高3 - 4数量级。但是如果我们希望访问某些非公有字段时,那我们还是无法使用DynamicMethodProxyFactory组件,还是需要使用反射。
这时,NonPublicPropertyProxy就派上用场了。这个组件是我根据NBear.Mapping中对属性的读写原理抽取出来的。由于它仍然是基于IL和CodeGenerator,因此在性能仍然具备DynamicMethodProxyFactory的特点。
该组件实现的功能,通过代理非常简单的支持对任意实例属性(Property)/字段(Field)的读写,支持任意静态字段的读写。但不支持静态属性的读写(对静态属性的读写还得通过DynamicMethodProxyFactory)。
由于该组件会动态组织IL代理函数,因此在首次获取代理方法时,会需要一些性能损失(DynamicMethodProxyFactory也是如此)。因此如果只需一次读写非公有属性/字段时,还是尽可能选择其它方式,比如反射。
使用演示:
code 1 设置私有字段值
1 User user = new User(); 2 NonPropertySetterDelegate nameSetter = NonPublicPropertyProxyFactory.GetPropertySetter(typeof(User), "name"); 3 NonPropertySetterDelegate idSetter = NonPublicPropertyProxyFactory.GetPropertySetter(typeof(User), "id"); 4 NonPropertySetterDelegate statusSetter = NonPublicPropertyProxyFactory.GetPropertySetter(typeof(User), "status"); 5 NonPropertySetterDelegate childrenSetter = NonPublicPropertyProxyFactory.GetPropertySetter(typeof(User), "Children"); 6 NonPropertySetterDelegate staticFieldSetter = NonPublicPropertyProxyFactory.GetPropertySetter(typeof(User), "staticValue"); 7 8 string name = "abu"; 9 nameSetter(user, name); 10 11 int i = 995006; 12 idSetter(user, i); 13 14 statusSetter(user, UserStatus.Admin); 15 16 List<string> children = new List<string>(); 17 childrenSetter(user, children); 18 19 staticFieldSetter(null, 100); 20
CODE 2 读取私有字段值
User user = new User(995006, "abu", UserStatus.Admin); user.Children = new List<string>(); NonPropertyGetterDelegate nameGetter = NonPublicPropertyProxyFactory.GetPropertyGetter(typeof(User), "name"); NonPropertyGetterDelegate idGetter = NonPublicPropertyProxyFactory.GetPropertyGetter(typeof(User), "id"); NonPropertyGetterDelegate statusGetter = NonPublicPropertyProxyFactory.GetPropertyGetter(typeof(User), "status"); NonPropertyGetterDelegate childrenGetter = NonPublicPropertyProxyFactory.GetPropertyGetter(typeof(User), "Children"); NonPropertyGetterDelegate staticFieldGetter = NonPublicPropertyProxyFactory.GetPropertyGetter(typeof(User), "staticValue"); int id = (int)idGetter(user); string name = nameGetter(user).ToString(); UserStatus status = (UserStatus)statusGetter(user); List<string> children = (List<string>)childrenGetter(user); int staticFieldValue = (int)staticFieldGetter(null);
性能:
写属性/字段时,与反射的时间对比:
次数(Ticks) DynamicPropertySetter|ReflectPeropertySetter|
1 111439(111439.00) |2822(2822.00) |
101 2133(21.33) |6365(63.65) |
201 4116(41.16) |6451(64.51) |
301 2661(26.61) |6256(62.56) |
401 2165(21.65) |16358(163.58) |
501 3506(35.06) |6948(69.48) |
601 2119(21.19) |6232(62.32) |
701 2636(26.36) |6260(62.60) |
801 4607(46.07) |8072(80.72) |
901 2085(20.85) |6269(62.69) |
1001 2136(21.36) |6780(67.80) |
1101 2040(20.40) |6256(62.56) |
1201 2080(20.80) |6997(69.97) |
读属性/字段时,与反射的时间对比:
次数(Ticks) DynamicPropertyGetter|ReflectPeropertyGetter|
1 21324(21324.00) |2834(2834.00) |
101 2096(20.96) |5719(57.19) |
201 2077(20.77) |6130(61.30) |
301 5368(53.68) |5729(57.29) |
401 2091(20.91) |5528(55.28) |
501 2086(20.86) |6077(60.77) |
601 2101(21.01) |5591(55.91) |
701 2094(20.94) |5979(59.79) |
801 2164(21.64) |5780(57.80) |
901 2137(21.37) |5463(54.63) |
1001 2071(20.71) |5523(55.23) |
1101 2096(20.96) |5576(55.76) |
1201 2083(20.83) |5566(55.66) |
1301 2135(21.35) |5827(58.27) |
1401 1996(19.96) |5457(54.57) |
1501 2518(25.18) |5513(55.13) |
1601 2007(20.07) |5537(55.37) |
1701 2014(20.14) |6128(61.28) |