【问题标题】:VB Linq sorting using dynamic expressions on dynamic objects在动态对象上使用动态表达式的 VB Linq 排序
【发布时间】:2017-04-04 21:36:14
【问题描述】:

我有一个派生自 DynamicObject 的类。我想使用属性(作为 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)

对

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 类型不支持 OrderBy 或 OrderByDescending。

任何人都可以提出一种在 VB 中使其工作的方法或提出一个实际工作的替代示例。将动态更改为对象不起作用,因为动态表达式编译器拒绝在运行时编译表达式,因为返回的是字符串而不是对象。

我检查了许多示例,但在尝试对动态对象进行排序时,它们似乎都无法正常工作,而且其中许多无法在带有 .Net Framework 4 的 VS 2010 VB 中编译。甚至是获得上述内容的方法在 VB 中工作的排序函数将不胜感激。

【问题讨论】:

    标签: vb.net linq dynamic lambda vb.net-2010


    【解决方案1】:

    您可以使用通用表达式树来调用 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
    

    【讨论】:

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