有没有办法避免FieldAccessException?

时间:2011-02-11 10:46:51

标签: .net reflection.emit

我们有一个类库,可以执行一些类似于ORM的基本操作,基本上我们可以这样做:

conn.Query<EntityType>("select * from table");

并取回List<EntityType>。由于从列名到实体类型的属性的映射存储在实体类型中,因此我们可以在需要时只使用属性的子集轻松构造基本对象。

问题是,这段代码很大程度上依赖于反射,我们发现我们知道的开销远大于我们的预期。

与“select * from table”相关的各种操作的示例时间:

  1. IDataReader,遍历所有行,178ms
  2. IDataReader,调用GetValues获取object []数组,对于所有行,260ms
  3. IDataReader,调用GetValues,构造新对象并添加到列表,对于所有行,356ms
  4. IDataReader,调用GetValues,构造新对象,使用反射将值复制到属性,~10.500ms( 29x步骤3 。)
  5. 我们缓存所涉及的反射,但仍然有太多的开销。

    由于99%的对象都是带有(1或2个支持字段)的简单属性,我想我可以通过IL / DynamicMethod生成以下代码:

    instance._Id = (int)value;
    

    这与FieldAccessException失败,我认为这是因为字段是私有的。有没有办法让我生成这个代码,或者我只是安全地咆哮错误的树?

2 个答案:

答案 0 :(得分:6)

是;在DynamicMethod中,您需要告诉它与EntityType关联;然后访问问题就消失了。使用将owner设置为typeof(EntityType),将skipVisibility设置为true的重载。

但是,在大多数情况下,您应该能够像字段一样快速地移动属性。所以除非有充分的理由选择字段,否则更喜欢这些属性。当然,如果使用属性,您可以通过装饰最合适的方式让用户决定。

答案 1 :(得分:0)

为什么不让属性读/写并调用“set property”方法而不是尝试直接写入支持属性?

这也有一个优点,即如果实现类使用了自动生成的属性(例如字符串名称{get; set;} >那么您的代码解决方案仍然可以工作,因为它不会产生任何关于如何实施财产的假设。