.net 如何使用LINQ或Lambda基于子属性订购集合?
我得到以下提供的字符串表达式: “ChildObject.FullName”…其中ChildObject是MyObject1类型的实例属性 ChildObject有一个名为“FullName”的属性,我想根据这个子属性“FullName”值对类型为“MyObject1”的集合进行排序 我可以整天直接在MyObject1上的属性上执行此操作,但在子实例上执行此操作时,我遇到了两个难题,无法让所有的部分都正常工作。主要的两个挑战是:.net 如何使用LINQ或Lambda基于子属性订购集合?,.net,vb.net,linq,lambda,.net,Vb.net,Linq,Lambda,我得到以下提供的字符串表达式: “ChildObject.FullName”…其中ChildObject是MyObject1类型的实例属性 ChildObject有一个名为“FullName”的属性,我想根据这个子属性“FullName”值对类型为“MyObject1”的集合进行排序 我可以整天直接在MyObject1上的属性上执行此操作,但在子实例上执行此操作时,我遇到了两个难题,无法让所有的部分都正常工作。主要的两个挑战是: MyObject1有几个不同的子属性类型,因此我无法硬编码Chil
'SortExpression below is a String like: "ChildObject.FullName"
MyObject1List = MyObject1List.OrderBy(Function(x)
Dim t As Type = x.GetType()
Dim tp As Type = t.GetProperty(SortExpression.Split(".").ElementAt(0)).PropertyType()
Return tp.GetProperty(Request.CompareExpression.Split(".").ElementAt(1))
End Function).ToList()
在表达式的最后一行返回的值之上(如果我在OrderBy方法之外运行代码,则会提供我所需的“全名”信息。因此代码必须接近,但仍然不起作用
关于如何实现这一点,有什么想法吗?我试图阻止的是对子类型上的一系列“If”块进行硬编码,然后将其类型硬编码为sort或OrderBy方法
谢谢!如果我正确理解了这个问题(免责声明-这是我编写的第一个vb.net代码,从语法上讲可能不是最好的-我是用c#first编写的),实现这一点的一种方法是执行以下操作 假设您的MyObject 1如下所示:
Public Class MyObject1
Private mChildObject As SortableChildObject
Public Property ChildObject() As SortableChildObject
Get
ChildObject = mChildObject
End Get
Set(value As SortableChildObject)
mChildObject = value
End Set
End Property
End Class
' Implement IComparable using reflection - just look up the property to
' sort on based on the "SortExpression" property
Public MustInherit Class SortableChildObject
Implements IComparable
Protected MustOverride ReadOnly Property SortExpression() As String
Public Function CompareTo(obj As Object) As Integer Implements System.IComparable.CompareTo
' Make sure the object we are comparing to is also our type
Dim oo As SortableChildObject = TryCast(obj, SortableChildObject)
If oo Is Nothing Then
Throw New ArgumentException("I cannot compare these two objects")
End If
' Get the value to sort on for this object
Dim thisVal As IComparable = GetSortableValue(Me, SortExpression)
If thisVal Is Nothing Then
Throw New ArgumentException("Could not get the value of the sortable property for this")
End If
' Get the value to sort on for the object we are comparing to
Dim thatVal As IComparable = GetSortableValue(oo, oo.SortExpression)
If thatVal Is Nothing Then
Throw New ArgumentException("Could not get the value of the sortable property for that")
End If
' Use the IComparable implementation of the properties we are comparing
Return thisVal.CompareTo(thatVal)
End Function
Private Function GetSortableValue(obj As Object, sortExpression As String) As IComparable
Dim prop As PropertyInfo = obj.GetType().GetProperty(sortExpression)
If prop Is Nothing Then
Throw New ArgumentException("Could not find the property " + sortExpression)
End If
Dim val As Object = prop.GetValue(obj, Nothing)
Dim ret As IComparable = TryCast(val, IComparable)
If ret Is Nothing Then
Throw New ArgumentException("No way to compare the values as the comparable property does not implement IComparable")
End If
Return ret
End Function
End Class
' This is a child object that has a string property called "FullName" which
' is what we want to sort on
Public Class FullNameChildObject
Inherits SortableChildObject
Private mFullName As String
Protected Overrides ReadOnly Property SortExpression() As String
Get
SortExpression = "FullName"
End Get
End Property
Public Property FullName() As String
Get
FullName = mFullName
End Get
Set(value As String)
mFullName = value
End Set
End Property
End Class
请注意,它的属性必须是“SortableChildObject”-该类如下所示:
Public Class MyObject1
Private mChildObject As SortableChildObject
Public Property ChildObject() As SortableChildObject
Get
ChildObject = mChildObject
End Get
Set(value As SortableChildObject)
mChildObject = value
End Set
End Property
End Class
' Implement IComparable using reflection - just look up the property to
' sort on based on the "SortExpression" property
Public MustInherit Class SortableChildObject
Implements IComparable
Protected MustOverride ReadOnly Property SortExpression() As String
Public Function CompareTo(obj As Object) As Integer Implements System.IComparable.CompareTo
' Make sure the object we are comparing to is also our type
Dim oo As SortableChildObject = TryCast(obj, SortableChildObject)
If oo Is Nothing Then
Throw New ArgumentException("I cannot compare these two objects")
End If
' Get the value to sort on for this object
Dim thisVal As IComparable = GetSortableValue(Me, SortExpression)
If thisVal Is Nothing Then
Throw New ArgumentException("Could not get the value of the sortable property for this")
End If
' Get the value to sort on for the object we are comparing to
Dim thatVal As IComparable = GetSortableValue(oo, oo.SortExpression)
If thatVal Is Nothing Then
Throw New ArgumentException("Could not get the value of the sortable property for that")
End If
' Use the IComparable implementation of the properties we are comparing
Return thisVal.CompareTo(thatVal)
End Function
Private Function GetSortableValue(obj As Object, sortExpression As String) As IComparable
Dim prop As PropertyInfo = obj.GetType().GetProperty(sortExpression)
If prop Is Nothing Then
Throw New ArgumentException("Could not find the property " + sortExpression)
End If
Dim val As Object = prop.GetValue(obj, Nothing)
Dim ret As IComparable = TryCast(val, IComparable)
If ret Is Nothing Then
Throw New ArgumentException("No way to compare the values as the comparable property does not implement IComparable")
End If
Return ret
End Function
End Class
' This is a child object that has a string property called "FullName" which
' is what we want to sort on
Public Class FullNameChildObject
Inherits SortableChildObject
Private mFullName As String
Protected Overrides ReadOnly Property SortExpression() As String
Get
SortExpression = "FullName"
End Get
End Property
Public Property FullName() As String
Get
FullName = mFullName
End Get
Set(value As String)
mFullName = value
End Set
End Property
End Class
现在您必须做的是确保要排序的所有内容都继承自该类,例如,假设我们有一个具有“FullName”字符串属性的对象,它将如下所示:
Public Class MyObject1
Private mChildObject As SortableChildObject
Public Property ChildObject() As SortableChildObject
Get
ChildObject = mChildObject
End Get
Set(value As SortableChildObject)
mChildObject = value
End Set
End Property
End Class
' Implement IComparable using reflection - just look up the property to
' sort on based on the "SortExpression" property
Public MustInherit Class SortableChildObject
Implements IComparable
Protected MustOverride ReadOnly Property SortExpression() As String
Public Function CompareTo(obj As Object) As Integer Implements System.IComparable.CompareTo
' Make sure the object we are comparing to is also our type
Dim oo As SortableChildObject = TryCast(obj, SortableChildObject)
If oo Is Nothing Then
Throw New ArgumentException("I cannot compare these two objects")
End If
' Get the value to sort on for this object
Dim thisVal As IComparable = GetSortableValue(Me, SortExpression)
If thisVal Is Nothing Then
Throw New ArgumentException("Could not get the value of the sortable property for this")
End If
' Get the value to sort on for the object we are comparing to
Dim thatVal As IComparable = GetSortableValue(oo, oo.SortExpression)
If thatVal Is Nothing Then
Throw New ArgumentException("Could not get the value of the sortable property for that")
End If
' Use the IComparable implementation of the properties we are comparing
Return thisVal.CompareTo(thatVal)
End Function
Private Function GetSortableValue(obj As Object, sortExpression As String) As IComparable
Dim prop As PropertyInfo = obj.GetType().GetProperty(sortExpression)
If prop Is Nothing Then
Throw New ArgumentException("Could not find the property " + sortExpression)
End If
Dim val As Object = prop.GetValue(obj, Nothing)
Dim ret As IComparable = TryCast(val, IComparable)
If ret Is Nothing Then
Throw New ArgumentException("No way to compare the values as the comparable property does not implement IComparable")
End If
Return ret
End Function
End Class
' This is a child object that has a string property called "FullName" which
' is what we want to sort on
Public Class FullNameChildObject
Inherits SortableChildObject
Private mFullName As String
Protected Overrides ReadOnly Property SortExpression() As String
Get
SortExpression = "FullName"
End Get
End Property
Public Property FullName() As String
Get
FullName = mFullName
End Get
Set(value As String)
mFullName = value
End Set
End Property
End Class
因此,为了使用它,让我们构建一个小对象列表来进行排序,如下所示:
Dim myObject1List As New List(Of MyObject1)
Dim i As FullNameChildObject = New FullNameChildObject
i.FullName = "B"
Dim o As New MyObject1
o.ChildObject = i
myObject1List.Add(o)
i = New FullNameChildObject
i.FullName = "A"
o = New MyObject1
o.ChildObject = i
myObject1List.Add(o)
i = New FullNameChildObject
i.FullName = "D"
o = New MyObject1
o.ChildObject = i
myObject1List.Add(o)
i = New FullNameChildObject
i.FullName = "C"
o = New MyObject1
o.ChildObject = i
myObject1List.Add(o)
根据ChildObject属性对其进行排序非常简单,只需执行以下操作:
Dim ret = myObject1List.OrderBy(Function(x)
Return x.ChildObject
End Function)
这就是你需要的吗?这样做有点问题——正如你看到的,有很多地方可能会出错——例如,如果你混合了你想要比较的对象(比如,你有一个按整数排序,另一个按字符串排序)它将引发异常。如果我理解正确,您有一个包含对象(例如,子对象)的对象(例如,父对象)。子对象有一个字段全名,您希望按子对象全名对父对象列表进行排序 如果是这样,那么,OrderBy()应该为您做这件事 假设我们有一份父母名单 父{Id=1,子{Id=1,FullName=“Jan”} 父{Id=2,子{Id=2,FullName=“Feb”} 父{Id=3,子{Id=3,FullName=“Mar”} 父{Id=4,子{Id=4,FullName=“Apr”} 使用OrderBy()对它们进行排序 给予 父{Id=4,子{Id=4,FullName=“Apr”} 父{Id=2,子{Id=2,FullName=“Feb”} 父{Id=1,子{Id=1,FullName=“Jan”} 父{Id=3,子{Id=3,FullName=“Mar”} (下面的例子) hth,
艾伦 编辑 请重新阅读问题。您有不同的全名属性,它们是按名称选择的(从查询字符串中选择的?) 可以使用常规形状的表达式(请参见)按名称选择特性 如果所选属性是IComparable(或者是IEquatable?不太确定是哪个),则OrderBy()仍将工作。这意味着只要排序字段是基本类型,就可以了。如果它们是自定义类型(对象),则需要做更多的工作 很抱歉第一次答错了 更多编辑 今天是星期五,这里的速度很慢: 好的,扩展了答案以按名称访问不同的子成员。(我使用了字段而不是属性,但两者都可以使用)。我们仍然需要知道字段的类型,但如果需要,再多做一点工作可能会删除该字段
私有类子类
作为整数的公共Id
作为字符串的公共全名
末级
私有类父类
作为整数的公共Id
作为儿童的公共儿童
末级
从{_
具有{_
Key.Id=1_
Key.Child=带有{_
Key.Id=1_
Key.FullName=“Jan”_
} _
}, _
具有{_
Key.Id=2_
Key.Child=带有{_
Key.Id=2_
Key.FullName=“Feb”_
} _
}, _
具有{_
Key.Id=3_
Key.Child=带有{_
Key.Id=3_
Key.FullName=“Mar”_
} _
}, _
具有{_
Key.Id=4_
Key.Child=带有{_
Key.Id=4_
Key.FullName=“Apr”_
} _
} _
}
_
公共子SortByChildName()
Dim expectedparentId=New(){4,2,1,3}
Dim sortedIds=Items.OrderBy(SelectExpression(父级,字符串)(“Child.FullName”))。[Select](函数(itm)itm.Id)
Assert.IsTrue(ExpectedParentId.SequenceEqual(SortedDids))
端接头
_
公共子SortByChildId()
Dim expectedParentIds=New(){4,3,2,1}
Dim sortedIds=Items.OrderBy(SelectExpression(父级,整数)(“Child.Id”)。[Select](函数(itm)itm.Id)
Assert.IsTrue(ExpectedParentId.SequenceEqual(SortedDids))
端接头
公共共享函数SelectExpression(属于TItem,TField)(字段名为字符串)作为Func(属于TItem,TField)
Dim type=GetType(TItem)
Dim字段=字段名。拆分(“.”C)
Dim arg As ParameterExpression=Expression.Parameter(类型为“项”)
Dim expr As表达式=arg
将每个字段作为字段中的字符串
Dim fieldInfo=类型.GetField(字段)
expr=Expression.Field(expr,fieldInfo)
type=fieldInfo.FieldType
下一个
返回表达式.Lambda(很有趣