【问题标题】:LINQ, Visual Basic, & Reflection: capitalization of field names from queries returning anonymous typeLINQ、Visual Basic 和反射:来自返回匿名类型的查询的字段名称大写
【发布时间】:2014-01-14 17:34:57
【问题描述】:

编辑以回答我自己的问题。这似乎是一个 LINQ/VB 错误。

返回异常类型的简单 LINQ 查询有时会更改查询中指定的字段名称,以便将它们大写。或许将查询结果作为参数传递给方法调用:

someThing.someMethod(From someStuff In stuffList _
                     Select text = someStuff.Name(), _
                            value = someStuff.Id
                     )

someMethod 有签名的地方

Public Sub someMethod(ByVal list As IEnumerable(Of Object))

如果您步入someMethod 的执行,然后在quickwatch 中检查list 的值,您可能会看到字段名称为“text”&“value”或“Text”&“Value”。

LINQ 查询不应更改查询中指定的字段名称,因此正确的行为是字段名称“文本”和“值”。然而,我们的应用程序的生产版本具有不正确的大写行为(可以间接确定),而调试版本显示它在不同时间和/或在不同开发人员的机器上以两种方式发生。

对于控制此行为的 LINQ 的某些功能,我已经看高和低了,但现在几乎可以肯定它是一个错误。 (msdn forum thread, MS Connect bug page)

这很可能只有在使用反射时才会出现问题,比如type.getfield()比如in

listItem = list.ElementAt(index)
itemTextField = listItem.GetType().GetField("text")
itemText = CType(itemTextField.GetValue(listItem),String)

如果您遇到这种情况,解决方法是使用 GetField 的重载和绑定标志,使其不区分大小写:

itemTextField = listItem.GetType().GetField("text", BindingFlags.IgnoreCase)

遇到此错误一定非常罕见,但如果他们在这里找到此信息,下一个人可能会花更少的时间挠头。

=========原帖=========== 在我的调试构建环境中获得与在我的同事和我们的生产环境中不同的行为,与 LINQ 和反射有关...

在运行遗留代码的调试版本时,以下代码

    Dim objectType As Type = obj.GetType()
    Dim field As FieldInfo = objectType.GetField(name)
    Dim prop As PropertyInfo = objectType.GetProperty(name)

Nothing 对应 fieldprop

obj 的值是从上面向下传递的,是 LINQ 查询的结果(它是查询生成的列表的单个元素):

    From bpt In CustomBProcessTypes Select text = bpt.Name(), value = bpt.Id

name的值也是从上面传过来的,是“Text”(注意大写)。 我可以在调试器中检查 obj 并确认 LINQ 查询创建的对象的字段名是“文本”和“值”(注意没有大写),这是我所期望的。

因此,无法通过大写名称找到字段是有道理的。但是,我们的生产构建和我的同事构建没有这个问题。

因为对 type.getfield(string) 的调用是明确区分大小写的,所以我现在唯一能想到的就是必须有一些与列/字段名自动大写相关的 LINQ 配置,而我的环境是与其他设置不同。

使用 Visual Studio 2012。我对 LINQ 本身一无所知。

有人知道这里会发生什么吗?

(注意:如果我有机会,我会让同事逐步完成相关代码,看看在他们的环境中,由 linq 查询创建的对象是否以大写的字段名称结尾)

编辑:我在他的调试版本中与一位同事进行了验证:他的 LINQ 查询创建了一个字段名称为“Text”和“Value”的对象列表,但在我的环境中,LINQ 查询以字段名称“text”结束和“价值”。代码是相同的,但在我的环境中如何配置 LINQ 肯定有一些问题,它无法自动大写这些字段名称,但在他们的机器和我们的生产环境中发生。

【问题讨论】:

    标签: vb.net linq visual-studio reflection capitalization


    【解决方案1】:

    我想某些编译器设置可能会导致不同的大小写。通常这不会有什么不同,因为 VB.NET 是一种不区分大小写的语言,所以 obj.Textobj.text 都可以正常工作。但是要在反射查找中使用不区分大小写,您需要通过在GetFieldGetProperty 的第二个参数中包含BindingFlags.IgnoreCase 来指定它:

    Dim field As FieldInfo = objectType.GetField(name,
        BindingFlags.Public Or BindingFlags.Instance Or BindingFlags.IgnoreCase)
    

    不过,我对name 的来源感到困惑。其他一些代码是从查询的反射中获取字段名称吗?我没有看到你的问题在哪里解释。

    【讨论】:

    • 谢谢,我觉得这让我更接近了解正在发生的事情。但是,由于我们只是使用重载 GetField(name) 并且默认值(通常)区分大小写,想知道我的同事机器上的生产构建或调试构建如何以某种方式默认为 BindingFlags.Ignorecase?
    • name 的值是 "Text",并作为参数,硬编码字符串在调用堆栈上几级。
    • @Greylander 我不是说GetField 调用会被改变,而是LINQ 语句可以用不同的字段名编译。但是,如果 name 以同样的方式从反射中提取,它应该与它运行的任何编译一致。 name 是硬编码还是以其他方式确定?
    • @Greylander 好的,那么您必须在另一台机器上使用大写的字段名称。使用绑定标志能解决问题吗?
    • 好的,我在他的调试版本中与一位同事进行了验证:他的 LINQ 查询创建了一个字段名称为“Text”和“Value”的对象列表,但在我的环境中,LINQ 查询以字段名称“文本”和“值”。代码是相同的,但是在我的环境中如何配置 LINQ 必须有一些东西无法自动大写这些字段名称,但这会发生在他们的机器和我们的生产环境中。我对 vb、visual studio 和 linq 太陌生了,不知道从哪里开始寻找。
    【解决方案2】:

    我已经回答了我自己的问题(尽可能)。归结为 LINQ/vb.net 中的一个错误。

    在原始帖子顶部进行了充分解释(已编辑)。希望这可以为将来节省一些时间。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多