Is there a better way to implement this? Should I be concerned about the performance of the Compile method here?
Public Overrides Function GetValidSerialNumbers() As System.Collections.Generic.IEnumerable(Of SerialNumber)
Return Queryable.Where(allSerials, SerialNumberValidFunc)
End Function
Public Overrides Function IsSerialNumberValid(serialNumber As SerialNumber) As Boolean
Return (SerialNumberValidFunc.Compile().Invoke(serialNumber))
End Function
Private ReadOnly Property SerialNumberValidFunc As Expressions.Expression(Of Func(Of SerialNumber, Boolean))
Get
If ProductionReceiptLine.MOOutput Is Nothing Then
Return Function(sn As SerialNumber) sn.ItemInventory Is Nothing AndAlso _
(sn.Status = SerialNumberStatusValues.Planned AndAlso sn.MO Is ProductionReceiptLine.ProductionReceipt.MO _
OrElse sn.Status = SerialNumberStatusValues.Assigned)
Else
Return Function(sn As SerialNumber) sn.ItemInventory Is Nothing AndAlso _
(sn.Status = SerialNumberStatusValues.Planned AndAlso sn.MO Is Nothing OrElse sn.Status = SerialNumberStatusValues.Assigned)
End If
End Get
End Property
The reason I want the lambda expression is because I want that function to be able to get all the way through LINQ-to-SQL to be converted to SQL. The reason I want the direct version is because I have other code that I want to validate individual serial numbers before submitting changes. And I fear that GetValidSerialNumbers.Contains(serialNumber) will execute a more-complex-than-necesssary query.
The Compile method is very slow because it needs to emit IL from your expression. Invoking the compiled function will cause another compile: the JIT compilation.
I suggest you cache the result of Compile in a static field or so.
The general approach you are taking is good. It is DRY.