Is there a way to implement Caliburn-like co-routines in VB.NET since there's no yield keyword
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.
Ev开发者_高级运维erything 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).
精彩评论