background image

        Conent: <%# (Container.DataItem as Comment).Content %><br />
        NickName: <%# this.GetUser((Container.DataItem as Comment).UserID).NickName %>
    ItemTemplate>
    <SeparatorTemplate>
        <hr />
    SeparatorTemplate>
asp:Repeater>
  兄弟们自己做判断吧。
嫌反射性能差?算有那么一点道理吧

……

  反射速度慢?我同意它是相对慢一些。
  反射占

CPU 多?我同意他是相对多一点。

  所以

Eval 不该使用?我不同意

——怎能把孩子和脏水一起倒了?我们把反射访问属性

的性能问题解决不就行了吗?
  性能差的原因在于

Eval 使用了反射,解决这类问题的传统方法是使用 Emit。但是.NET 

3.5 中现在已经有了 Lambda Expression,我们动态构造一个 Lambda Expression 之后可以通
过它的

Compile 方法来获得一个委托实例,至于 Emit 实现中的各种细节已经由.NET 框架

实现了

——这一切还真没有太大难度了。

public class DynamicPropertyAccessor
{
    private Func<object, object> m_getter;
    public DynamicPropertyAccessor(Type type, string propertyName)
        : this(type.GetProperty(propertyName))
    { }
    public DynamicPropertyAccessor(PropertyInfo propertyInfo)
    {
        // target: (object)((({TargetType})instance).{Property})
        // preparing parameter, object type
        ParameterExpression instance = Expression.Parameter(
            typeof(object), "instance");
        // ({TargetType})instance
        Expression instanceCast = Expression.Convert(
            instance, propertyInfo.ReflectedType);
        // (({TargetType})instance).{Property}
        Expression propertyAccess = Expression.Property(
            instanceCast, propertyInfo);
        // (object)((({TargetType})instance).{Property})
        UnaryExpression castPropertyValue = Expression.Convert(
            propertyAccess, typeof(object));
        // Lambda expression
        Expression<Func<object, object>> lambda = 
            Expression.Lambda<Func<object, object>>(
                castPropertyValue, instance);
        this.m_getter = lambda.Compile();
    }