Using PredicateBuilder with VB.NET

微笑、不失礼 提交于 2019-12-01 12:12:36

Here's the code that works for me in VB.NET, as I also tweaked this class to run in VB.NET...

Imports System.Linq.Expressions

Public Module PredicateBuilder
    Public Function [True](Of T)() As Expression(Of Func(Of T, Boolean))
        Return Function(f) True
    End Function

    Public Function [False](Of T)() As Expression(Of Func(Of T, Boolean))
        Return Function(f) False
    End Function

    <System.Runtime.CompilerServices.Extension()> _
    Public Function [Or](Of T)(ByVal expr1 As Expression(Of Func(Of T, Boolean)), ByVal expr2 As Expression(Of Func(Of T, Boolean))) As Expression(Of Func(Of T, Boolean))
        Dim invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast(Of Expression)())
        Return Expression.Lambda(Of Func(Of T, Boolean))(Expression.[Or](expr1.Body, invokedExpr), expr1.Parameters)
    End Function

    <System.Runtime.CompilerServices.Extension()> _
    Public Function [And](Of T)(ByVal expr1 As Expression(Of Func(Of T, Boolean)), ByVal expr2 As Expression(Of Func(Of T, Boolean))) As Expression(Of Func(Of T, Boolean))
        Dim invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast(Of Expression)())
        Return Expression.Lambda(Of Func(Of T, Boolean))(Expression.[And](expr1.Body, invokedExpr), expr1.Parameters)
    End Function
End Module

And here's how I use it:

Dim pred = PredicateBuilder.True(Of MyClass)()

pred = pred.And(Function(m As MyClass) m.SomeProperty = someValue)
pred = pred.Or(Function(m As MyClass) m.SomeProperty = someValue)

Solved the issue. It was because Option Infer was set to Off. As soon as I set it to On the correct type was infered and it all worked as it should.

One thing to bear in mind, though it may not solve your particular issue, is case-sensitivity when working with cross-language solutions.

C# and the CLR itself are case-sensitive; VB.NET is not. Depending on which way you're consuming the library, an exception may be thrown because the case does not match (and therefore fails to resolve to a known type).

This can happen if you think you've consistently declared your namespace names, but one class has the namespace declared with one character in upper case. This is very easy to do in Visual Basic, but to VB.NET, they all look like they've compiled down to a single, cohesive namespace. As far as the CLR is concerned though, they are two distinct namespaces.

I've run into this issue before, and it was a very elusive bug to track down.

I know you're consuming a C# project from VB.NET, but keep an eye out for those types of issues.

It works for me:

Dim predicate = PredicateBuilder.False(Of Integer)()
predicate = predicate.Or(Function(q) q Mod 2 = 0)

(I don't have your t_Quote type)

Also, it's horrible practice to have a type name like t_Quote. That should be called Quote; Hungarian notation and underscores are both frowned upon in C# names.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!