I have recreated the Predicatebuilder class in a seperate C# project and I'm trying to use it in a VB.NET project but I keep getting the following error:
Overload resolution failed because no accessible 'Or' accepts this number of arguments.
when I use it like so:
Dim predicate = PredicateBuilder.False(Of t_Quote)()
predicate = predicate.Or(Function(q) q.iQuoteType = iQuoteType)
The relivant project is referenced, I'm using the correct imports statement and it all compiles without any errors.
Any idea where I'm going wrong?
Here is the PredicateBuilder class in C# I'm using:
public static class PredicateBuilder
{
public static Expression> True() {
return f => true; }
public static Expression> False() {
return f => false; }
public static Expression<Func<T, bool>> Or<T>(this
Expression> expr1,
Expression> expr2)
{
var invokedExpr = Expression.Invoke(expr2,
expr1.Parameters.Cast());
return Expression.Lambda>
(Expression.OrElse(expr1.Body,
invokedExpr), expr1.Parameters);
}
public static Expression<Func<T, bool>> And<T>(this
Expression> expr1,
Expression> expr2)
{
var invokedExpr = Expression.Invoke(expr2,
expr1.Parameters.Cast());
return Expression.Lambda>
(Expression.AndAlso(expr1.Body,
invokedExpr), expr1.Parameters);
}
}
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.