Private Sub LoadData(Of T)(ByVal query As ObjectQuery(Of T),
ByRef result As IEnumerable(Of T))
If Connection.State = ConnectionState.Open Then
result = query.ToArray
Else
AddHandler Connection.StateChange,
Sub(sender As Object, e As StateChangeEventArgs)
LoadData(query, result)
End Sub
End If
End Sub
In the above code I am trying to recurse the LoadData function when the connection is unavailable, I want to defer the loading to when it becomes available.
The problem is the above code leads to a compiler error, since a ByRef
param cannot be used in lambda expressions.
Any idea of how to do this the right way?
You cannot use a ByRef
parameter in a lambda because it could be pointing to a location on the stack which no longer exists once the lambda execuetes. All you have to do is use a more "permanent" storage location. You can pass in an object with a property of IEnumerable(Of T)
that you can set in order to assign the result.
A probably better option is to pass in a delegate (Action<IEnumerable<T>>
) that accepts the result and performs whatever action the caller requires with the result. Here's an example in C#:
void LoadData<T>(ObjectQuery<T> query, Action<IEnumerable<T>> action)
{
if (Connection.State == ConnectionState.Open)
action(query.ToArray());
else
{
// create a lambda to handle the next state change
StateChangeEventHandler lambda = null;
lambda = (sender, e) =>
{
// only perform our action on transition to Open state
if (Connection.State == ConnectionState.Open)
{
// unsubscribe when we're done
Connection.StateChange -= lambda;
action(query.ToArray());
}
}
// subscribe to connection state changes
Connection.StateChange += lambda;
}
}
And you would invoke LoadData
like this:
LoadData(query, results => listBox.DataSource = results);
Note the nuances of my implementation. For example, it does not call itself within the event handler because that will cause it to resubscribe to the event if the handler is ever called with a state other than Open
. It also unsubscribes from the event once the connection opens. I'm not sure how this would translate to VB, but in C# this is a 3-step process. First you must declare a variable to hold the lambda and set its value to null. Then you create the lambda, which can now reference itself to unsubscribe. And finally you can use the lambda to subscribe to the event.