C'è un modo per implementare Caliburn-come co-routine in VB.NET poiché non c'è parola chiave yield
Domanda
Si noti che sono a conoscenza di altri href="https://stackoverflow.com/questions/97381/yield-in-vb-net"> in vb.net qui sul SO.
Sto giocando intorno con Caliburn ultimamente. Mazzo di grandi cose lì, tra cui co-routine implementazione.
La maggior parte del lavoro che sto facendo è C # basa, ma ora sono anche la creazione di una linea guida di architettura per un solo VB.NET negozio, sulla base di Rob piccolo quadro MVVM .
Tutto sembra molto bene, tranne usando co-routine da VB. Dal momento che VB 10 è usato, siamo in grado di provare qualcosa di simile di Bill McCarthy suggerimento :
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
Sono solo non riuscendo a comprendere come un metodo poco co-routine di più complessa come quella qui sotto (tratta da GameLibrary di Rob) potrebbe essere scritta 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();
}
Qualsiasi idea di come realizzare questo, o qualche idea su come utilizzare co-routine Caliburn in VB?
Modifica
Marco mi ha segnalato una giusta direzione. Dopo aver guardato in Reflector - codice Visual Basic di GameLibrary di Rob, sono riuscito a modificare la GenericIterator di Bill McCarthy a diventare macchina a stati di un uomo povero:
Private _state As Integer = -1
Public Function MoveNext() As Boolean Implements IEnumerator.MoveNext
_state += 1
Return _func(_Current, _state)
End Function
E possiamo usare in questo modo:
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
E 'sicuramente non è elegante come C # versione, ma sembra di essere fattibile. Vedremo se ci sono problemi con questo. Se qualcuno ha un'idea migliore, io sono tutto orecchi.
Soluzione
Per quanto ho capito, la soluzione VB si basa sulla omogeneità delle varie fasi; in altre parole, si ripete la stessa azione fino alla condizione di uscita è soddisfatta.
Caliburn co-routine, invece, sono utili nello scenario opposto: disomogenee (e asincroni) passi intrecciati con codice di controllo; ma questo è fondamentalmente una macchina a stati.
In realtà, Caliburn sfrutta compilatore C # per ottenere un'implementazione libera e generato automaticamente macchina a stati; quindi la soluzione potrebbe essere quella di costruire una semplice macchina a stati fatti a mano, proprio come quello costruito da compilatore C # (si veda http://blogs.msdn.com/wesdyer/archive/2007/03/23/all-about-iterators.aspx ).