【问题标题】:Does Entity Framework/LINQ to SQL Data Binding use reflection?实体框架/LINQ to SQL 数据绑定是否使用反射?
【发布时间】:2009-04-20 00:47:07
【问题描述】:

如果之前有人问过这个问题,请原谅我;我进行了搜索,但找不到任何具体回答此问题的内容,但我很乐意被推荐。

我正在查看实体框架和 LINQ to SQL,虽然我喜欢这些系统(当然还有 LINQ 集成),但我对数据绑定方面有点怀疑。我已经获取并检查了查询结果,它们似乎没有实现标准的 .NET 列表绑定接口(@98​​7654321@,更重要的是ITypedList),这让我相信将它们绑定到网格(或其他任何东西)将使用反射来获取/设置我的实体属性。这似乎是一个相对昂贵的操作,尤其是当所有代码都生成并且可以实现接口时。

有人对此有任何见解吗?反射是否用于获取/设置属性的值?如果是,这是否会对性能产生明显影响,是否有人知道他们为何选择这条路线?

编辑

我实际上专注于ITypedList 是否在此过程中的某个地方实现,因为它能够提供一种明确的机制来定义和与属性交互而无需诉诸反射。虽然我没有启动 LINQ to SQL 项目,但我确实检查了一个简单的 Entity Framework 实体查询结果,它似乎没有实现ITypedList。有谁知道我是否只是看错了东西,或者如果不是,为什么会这样?

编辑 2

在接受 Marc 的回答后,我认为如果我发布一些用于无缝实现他的解决方案的简单代码,可能对其他人有所帮助。我将以下内容放入我的类的静态构造函数中:

public static ContextName()
{
    foreach(Type type in System.Reflection.Assembly.GetExecutingAssembly()
        .GetTypes())
    {
        if (type.GetCustomAttributes(typeof(System.Data.Linq.Mapping
            .TableAttribute), true) != null)
        {
            System.ComponentModel.TypeDescriptor.AddProvider(
                new Hyper.ComponentModel.HyperTypeDescriptionProvider(
                    System.ComponentModel.TypeDescriptor.GetProvider(
                        type)), 
                type);
        }
    }
}

虽然这是针对 LINQ to SQL 的,但我确信可以为实体框架编写等效版本。这将扫描程序集以查找具有 Table 属性的任何类型,并为每个类型添加自定义提供程序。

【问题讨论】:

    标签: c# vb.net linq-to-sql entity-framework reflection


    【解决方案1】:

    支持 LINQ 等的表达式 API 是基于反射 (MemberInfo),而不是组件模型 (PropertyDescriptor 等) - 所以对ITypedList 的要求并不高。相反,内容是从IQueryable<T>IEnumerable<T>IList<T>等中的T推断出来的。

    你可能得到的最接近的是IListSource,但这仍然只是一个正确类型列表的浅包装。

    如果运行时绑定(到PropertyDescriptor)的性能是关键,您可能需要查看HyperDescriptor - 它使用Reflection.EmitTypeDescriptionProvider 来包装组件模型。

    关于“为什么”等;请注意,在几乎所有使用 LINQ-to-SQL 和 EF 的情况下,Expression(或“创建和设置成员”部分)将在调用之前编译为委托 - 所以在运行时没有巨大的反射成本。同样,对于 LINQ-to-Objects,一切都已经编译(由 C# 编译器)。

    【讨论】:

    • Marc,如果您的 HyperDescriptor 项目按我的预期工作,那将提供我所需要的。为什么微软不使用他们自己的数据绑定基础设施并依赖返回 ReflectPropertyDescriptors 的默认 TypeDescriptor 对我来说仍然有点困惑,但是哦,好吧。如果这行得通,我不在乎。
    【解决方案2】:

    根据我使用 LINQ to SQL 的经验,我得出的结论是 LINQ 使用反射来设置和获取实体类实例中的字段值。我不知道我是否能记住所有的原因,但我可以告诉你。

    1. 如果我没记错的话,LINQ 不会调用任何属性过程,而是直接设置和读取所有私有字段值,据我所知只能通过反射来完成。
    2. MetaData 提供的名称(在实体类属性的属性中)以字符串形式提供字段名称信息(例如,如果数据库列和属性名称不同)。您可以由此得出结论,LINQ 必须使用反射来查找成员以访问它。

    我认为这样做是为了实现简单性——您可以依赖实体类中字段中的值直接镜像数据库列值,并且从数据库中检索对象没有太多开销(填充新创建的与从数据库检索的值相对应的实体不应通过属性过程进行路由)。例如,我为表示从数据库中检索到的枚举值所做的一件事是将一些 LINQ 生成的属性设为私有,并将它们包装在读取和写入 LINQ 属性的部分类中的手动编码属性中。

    【讨论】:

      【解决方案3】:

      MSDN 对 LINQ to SQL 数据绑定的看法来看,它似乎确实使用了 IListSource 或 IBindingList。

      顺便说一句,LINQ 使用Expression Trees,这不像元编程那样是反射。性能应该比反射好得多。 Charlie Calvert 在article 中对此做了一些介绍。

      【讨论】:

      • 对,我知道它实现了 IListSource(结果是 IBindingList)。这里更重要的接口实际上是 ITypedList,因为它为每个属性提供了 PropertyDescriptor 对象的列表。如果没有 ITypedList 的显式实现(除非我遗漏了什么),BindingList 或 BindingSource 组件必须恢复为基于反射的 PropertyDescriptors,这将比显式时慢。
      • 此外,除非我有什么问题,否则表达式树与查询数据有关,而不是与检索查询数据以进行数据绑定操作有关。
      • 是的,树更适合查询。我只是觉得最好指出以防万一。如有误导,请见谅。
      猜你喜欢
      • 2010-09-05
      • 1970-01-01
      • 2011-04-27
      • 2011-01-15
      • 2010-11-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-29
      相关资源
      最近更新 更多