通用的访问非公有字段(Field)和属性组件

在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)         |