Есть ли способ реализовать Caliburn-подобные подпрограммы в VB.NET, так как нет ключевого слова yield - PullRequest
6 голосов
/ 27 марта 2010

Обратите внимание, что мне известны другие yield в vb.net вопросов здесь на SO.

Я играю с Caliburn в последнее время. Там куча отличных вещей, включая сопрограммы реализация.

Большая часть работы, которую я выполняю, основана на C #, но сейчас я также создаю руководство по архитектуре для магазина, предназначенного только для VB.NET, на основе небольшой инфраструктуры MVVM Роба .

Все выглядит очень хорошо, за исключением использования сопрограмм от VB. Поскольку используется VB 10, мы можем попробовать что-то вроде предложение Билла Маккарти :

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

Я просто не понимаю, как можно написать немного более сложный метод совместной работы, подобный приведенному ниже (взят из Rob's GameLibrary):

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();
}

Есть идеи, как этого добиться, или есть мысли по поводу использования сопрограмм Caliburn в VB?


Edit:

Марко указал мне правильное направление. Изучив код Reflector - Visual Basic в GameLibrary Роба, мне удалось изменить GenericIterator Билла Маккарти, чтобы он стал машиной состояния бедного человека:

Private _state As Integer = -1

Public Function MoveNext() As Boolean Implements IEnumerator.MoveNext
    _state += 1
    Return _func(_Current, _state)
End Function

И мы можем использовать это так:

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

Это определенно не так элегантно, как в версии C #, но выглядит вполне выполнимо. Посмотрим, есть ли проблемы с этим. Если у кого-то есть идея получше, я весь в ушах.

1 Ответ

3 голосов
/ 27 марта 2010

Насколько я понимаю, обходной путь VB основан на однородности различных шагов; другими словами, он повторяет одно и то же действие, пока не будет выполнено условие выхода.

Caliburn-подпрограммы вместо этого полезны в противоположном сценарии: неоднородные (и асинхронные) шаги, чередующиеся с управляющим кодом; но это в основном конечный автомат.

На самом деле, Caliburn использует компилятор C # для получения бесплатной и автоматически генерируемой реализации конечного автомата; поэтому решение может заключаться в создании простого конечного автомата, подобного тому, который был создан компилятором C # (см. http://blogs.msdn.com/wesdyer/archive/2007/03/23/all-about-iterators.aspx).

...