2017-04-04 44 views
2

我已經從DynamicObject派生的類動態表達式VB LINQ的排序。我想使用一個屬性來排序(作爲TypeDescriptor傳遞給BindingList的ApplyCoreSort)。我已經嘗試了很多來自這裏和其他站點的示例,但其中很多都是用C#編寫的,並且不能很好地轉換爲VB。我發現的方法,從這個MSDN blog是好的和簡單,但是當翻譯成VB失敗:使用關於動態對象

Private Shared Function Sort(source As IEnumerable, [property] As String) As DynamicEntity() 
    Dim binder__1 = RuntimeBinder.Binder.GetMember(CSharpBinderFlags.None, [property], GetType(Example3), New CSharpArgumentInfo() {CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, Nothing)}) 
    Dim param = Expression.Parameter(GetType(DynamicEntity), "o") 
    Dim getter = Expression.Dynamic(binder__1, GetType(Object), param) 
    Dim lambda = Expression.Lambda(Of Func(Of DynamicEntity, Object))(getter, param).Compile() 
    Return source.Cast(Of DynamicEntity)().OrderBy(lambda).ToArray() 
End Function 

主要是因爲原代碼依賴於動態類型的VB中的對象類型不能代替:

Func(Of DynamicEntity, Object) 

VS

Func<DynamicObject, dynamic> 

C#的等效低於:

private IEnumerable<DynamicObject> SortAscending(IEnumerable<DynamicObject> source, PropertyDescriptor property, ListSortDirection direction) 
    { 
     CallSiteBinder binder__1 = RuntimeBinder.Binder.GetMember(CSharpBinderFlags.None, property.Name, property.PropertyType, new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) }); 
     ParameterExpression param = Expression.Parameter(typeof(DynamicObject), "o"); 
     DynamicExpression getter = Expression.Dynamic(binder__1, property.PropertyType, param); 
     dynamic lambda = Expression.Lambda<Func<DynamicObject, dynamic>>(getter, param).Compile(); 
     if (direction == ListSortDirection.Ascending) { 
      return source.Cast<DynamicObject>().OrderBy(lambda).ToList; 
     } else { 
      return source.Cast<DynamicObject>().OrderByDescending(lambda).ToList; 
     } 
    } 

不幸的是,轉換回C#,並把它變成另一個DLL,因爲編譯器不工作抱怨了IEnumerable類型不支持排序依據或OrderByDescending。

任何人都可以提出一個辦法讓VB這種工作或暗示的實際工作的替代實例。由於動態表達式編譯器拒絕在運行時編譯表達式,因爲返回的是字符串而不是對象,所以將動態更改爲對象不起作用。

我已經檢查了一些例子,他們都不正常工作試圖動態對象進行排序時,許多人都不會在VS 2010中編譯VB與.Net框架4.即使一種方式來獲得的上面的排序功能在VB中工作將不勝感激。

回答

0

你可以使用一個通用的表達式樹來調用LINQ的排序依據(如答案here)?

我已經提供了答案在這裏爲了方便的VB版本(雖然不是作爲擴展名):

Public Shared Function Sort(Of T)(source As IQueryable(Of T), propertyName As String, sortOrder As ListSortDirection) As IQueryable(Of T) 
    Dim type = GetType(T) 
    Dim propertyInfo As PropertyInfo = type.GetProperty(propertyName) 
    Dim parameterExpression As ParameterExpression = Expression.Parameter(type, "p") 
    Dim propertyAccess As MemberExpression = Expression.MakeMemberAccess(parameterExpression, propertyInfo) 
    Dim sortExpression As LambdaExpression = Expression.Lambda(propertyAccess, parameterExpression) 
    Dim sortMethod = If(sortOrder = ListSortDirection.Ascending, "OrderBy", "OrderByDescending") 
    Dim resultExpression = Expression.[Call](
         GetType(Queryable), 
         sortMethod, 
         New Type() {type, propertyInfo.PropertyType}, 
         source.Expression, 
         Expression.Quote(sortExpression) 
        ) 
    Return source.Provider.CreateQuery(Of T)(resultExpression) 
End Function