views:

279

answers:

1

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.

+3  A: 

As far I understand, the VB workaround relies on the uniformity of the various steps; in other words, it repeats the same action until the exit condition is met.

Caliburn co-routines, instead, are useful in the opposite scenario: unhomogeneous (and asynchronous) steps interlaced with control code; but this is basically a state machine.

Actually, Caliburn leverages C# compiler to obtain a free and automatically generated state machine implementation; so the solution might be to build a simple hand-made state machine just like the one built by C# compiler (see http://blogs.msdn.com/wesdyer/archive/2007/03/23/all-about-iterators.aspx).

Marco Amendola
Great answer, you pretty much nailed the problem and possible solution there. Hopefully, I've managed to create some starting implementation for state machine (although not very elegant), after looking at compiler generated output in Reflector - Visual Basic code. Question is updated with this implementation.I'm still going to read the Wes Dyer's article, looks to have some good iterator infos there.Thanks!
Miroslav Popovic