使用匿名对象列表查询数组
Posted
技术标签:
【中文标题】使用匿名对象列表查询数组【英文标题】:Querying a Array with list of anonymous Object 【发布时间】:2021-04-17 03:45:43 【问题描述】:在我的应用程序中,我有一个对象数组, 所有对象的类型将始终相同但未知,但我需要根据某些条件更新数组对象的一个属性
我尝试使用反射来实现与下面相同的功能
Public Shared Sub FilterobjectArray(ByVal obj As Object())
Dim r = obj.Where(Function(x) CStr(x.[GetType]().GetProperty("Id")?.GetValue(x)) = "2")
For Each item In r
Dim propertyInfo As PropertyInfo = item.[GetType]().GetProperty("CompanyName")
propertyInfo.SetValue(item, Convert.ChangeType("MyCompany", propertyInfo.PropertyType), Nothing)
Next
End Sub
问题 我认为过滤数组的 Lambda 表达式是错误的,因为它在 x 中抛出“未设置对象引用”
我的示例实现
公司实体
Public Class Company
Public Property Id As Integer
Public Property CompanyName As String
End Class
实施
Dim comp(2) As Object
Dim comp1 = New Company With .Id = 1, .CompanyName = "Comp1"
Dim comp2 = New Company With .Id = 2, .CompanyName = "Comp2"
comp(0) = comp1
comp(1) = comp2
FilterobjectArray(comp)
有人可以提出什么问题吗,也欢迎 C# 答案或语法
注意:在 for 循环中第一次迭代后出现错误 即在第一个“propertyInfo.SetValue”完成并且下一次迭代开始之后
【问题讨论】:
为什么需要使用反射?你不能简单地使用一个界面来代替吗? 因为我们不知道对象的类型,所以我们使用反射来根据属性值进行过滤 您没有将任何项目添加到数组中。当您将数组传递给FilterobjectArray
时,该数组具有三个Nothing
值。
我使用Telerik Code converter 将您的 VB 代码转换为 C#,它确实将其转换为具有 3 个插槽的对象数组。而且它们都没有设置。
@SreenathGanga 我会重复彼得的评论。为什么不使用接口?如果您知道属性的名称,那么您已经对类型足够了解。你不需要反思。充其量,您需要过滤不实现接口的对象,例如OfType<>()
【参考方案1】:
这是您需要的代码:
Sub Main
Dim comp(1) As Object
comp(0) = New Company With .Id = 1, .CompanyName = "Comp1"
comp(1) = New Company With .Id = 2, .CompanyName = "Comp2"
FilterobjectArray(comp)
End Sub
Public Shared Sub FilterobjectArray(ByVal obj As Object())
Dim r = obj.Where(Function(x) CStr(x.[GetType]().GetProperty("Id")?.GetValue(x)) = "2")
For Each item As Object In r
Dim propertyInfo As PropertyInfo = item.[GetType]().GetProperty("CompanyName")
propertyInfo.SetValue(item, Nothing)
Next
End Sub
您需要先将元素添加到数组中。其他大部分都很好,我只是简化了SetValue
调用。
【讨论】:
谢谢.. 但这不是问题,我已经完成了数组填充实际代码但忘记在 SO 中添加它。抱歉,我已经更新了问题,还添加了错误消息 第一个“propertyInfo.SetValue(item,Nothing)”后出现错误 谢谢..在阅读了彼得和凯乌斯之后我明白了你的意思【参考方案2】:与在 C# 中声明数组大小的地方不同,在 VB 中声明数组时,需要指定最后一个有效索引。这意味着声明为 object(2)
的数组有 3 个插槽 - 0(数组从 0 开始)、1 和 2。您放置了 2 个对象,因此第三个插槽为空。
然后 ForEach 命中第三个空槽,但有一个转折:
错误窗口告诉你 x 什么都不是,x 是 LINQ 查询中使用的变量。 LINQ 查询不会在您说Where
的行上运行,它会在您使用 ForEach 中的变量 r 时立即运行。所以看起来它是导致错误的第一项,因为 ForEach 正在爆炸,但事实并非如此:事实是 LINQ 执行(将在第三个插槽上遇到错误)被延迟,直到您枚举 LINQ 查询的结果。如果您在 Where 末尾添加 .ToList()
调用,则代码将在您的 ForEach 之前崩溃..
将另一个对象添加到索引 2 中的数组中,将数组减少为 object(1)
或提供一些保护以防止 x 为 Nothing,如果您的系统在运行时自然会遇到空对象
【讨论】:
以上是关于使用匿名对象列表查询数组的主要内容,如果未能解决你的问题,请参考以下文章