Note that I'm aware of other yield in vb.net questions here on SO.
I'm playing around with Caliburn lately. Bunch of great stuff there, including co-routines implementation.
Most of the work I'm doing is C# based, but now I'm also creating an architecture guideline for a VB.NET only shop, based on Rob's small MVVM framework.
Everything looks very well except using co-routines from VB. Since VB 10 is used, we can try something like Bill McCarthy's suggestion:
Public Function Lines(ByVal rdr as TextReader) As IEnumerable(Of String)
Return New GenericIterator(Of String)
(Function(ByRef nextItem As String) As Boolean
nextItem = rdr.ReadLine
Return nextItem IsNot Nothing
End Function)
End Function
I'm just failing to comprehend how a little more complex co-routine method like the one below (taken from Rob's GameLibrary) could be written in VB:
public IEnumerable<IResult> ExecuteSearch()
{
var search = new SearchGames
{
SearchText = SearchText
}.AsResult();
yield return Show.Busy();
yield return search;
var resultCount = search.Response.Count();
if (resultCount == 0)
SearchResults = _noResults.WithTitle(SearchText);
else if (resultCount == 1 && search.Response.First().Title == SearchText)
{
var getGame = new GetGame
{
Id = search.Response.First().Id
}.AsResult();
yield return getGame;
yield return Show.Screen<ExploreGameViewModel>()
.Configured(x => x.WithGame(getGame.Response));
}
else SearchResults = _results.With(search.Response);
yield return Show.NotBusy();
}
Any idea how to achieve that, or any thoughts on using Caliburn co-routines in VB?
Edit:
Marco pointed me to a right direction. After looking in Reflector - Visual Basic code of Rob's GameLibrary, I managed to modify Bill McCarthy's GenericIterator to become a poor man's state machine:
Private _state As Integer = -1
Public Function MoveNext() As Boolean Implements IEnumerator.MoveNext
_state += 1
Return _func(_Current, _state)
End Function
And we can use it like this:
Public Function ExecuteSearch() As IEnumerable(Of String)
' If we need some variable shared across states, define it here
Dim someSharedStuff As String = String.Empty
' Notice the second lambda function parameter below - state
Return New GenericIterator(Of IResult)
(Function(ByRef nextItem As IResult, state As Integer) As Boolean
Select Case state
Case 0
someSharedStuff = "First state"
nextItem = Show.Busy
Return True
Case 1
nextItem = Show.SomeLoadingScreen
' Do some additional processing here...
Return True
Case 2
' Do something with someSharedStuff variable...
Console.WriteLine(someSharedStuff)
nextItem = PerforSomemWebServiceCall()
Return True
'...
Case 6
nextItem = Show.NotBusy
Return False
End Select
Return False
End Function)
End Function
It definitely isn't as elegant as C# version, but it looks to be doable. We'll see if there are any problems with this. If anyone has better idea, I'm all ears.