2017-04-04 19 views
2

私はDynamicObjectから派生したクラスを持っています。 BindingList ApplyCoreSortにTypeDescriptorとして渡されるプロパティを使用してソートしたいと思います。私はここや他のサイトからいくつかの例を試しましたが、それらの多くはC#にあり、VBにうまく翻訳されません。私は、このMSDN blogからの方法がいいとシンプルであることが判明したが、VBに翻訳されたとき、それは失敗します。VB Linq動的オブジェクトの動的式を使用した並べ替え

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; 
     } 
    } 

残念ながら、コンパイラがIEnumerable型がOrderByまたはOrderByDescendingをサポートしていないと不平を言うと、残念なことに、C#に変換して別のDLLに入れても機能しません。

誰でもVBでこれを動作させる方法を提案したり、実際に動作する別の例を提案することはできます。文字列がオブジェクトではなく返されているため、動的式コンパイラは実行時に式をコンパイルするのを拒否するため、動的からオブジェクトへの変更は機能しません。

私はいくつかの例をチェックしましたが、動的オブジェクトをソートしようとすると正しく動作しないようですが、その多くはVS 2010 VBで.Net Framework 4でコンパイルされません。上記のソート機能はVBで動作するようになります。

答えて

0

linqのOrderByを呼び出すために汎用式ツリーを使用することができます(答えは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 
関連する問題