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.
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With