代码之家  ›  专栏  ›  技术社区  ›  Miroslav Popovic

既然没有yield关键字,有没有办法在VB.NET中实现类似Caliburn的co例程

  •  6
  • Miroslav Popovic  · 技术社区  · 14 年前

    yield in vb.net 问题就在这里。

    Caliburn 最近。很多很棒的东西,包括 co-routines

    small MVVM framework .

    一切看起来都很好,除了使用VB的co例程。由于使用了vb10,我们可以尝试 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
    

    我只是不明白下面这种稍微复杂一点的协同例程方法(取自Rob的游戏库)是如何用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();
    }
    

    你知道如何实现这一点吗?或者你对在VB中使用Caliburn co例程有什么想法吗?


    编辑:

    Marco 给我指出了一个正确的方向。在查看了Rob游戏库的Reflector-Visual Basic代码后,我成功地修改了Bill McCarthy的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 回复  |  直到 7 年前
        1
  •  3
  •   Marco Amendola    14 年前

    据我所知,VB解决方案依赖于各个步骤的一致性;换句话说,它重复相同的操作,直到满足退出条件。

    相反,caliburnco例程在相反的场景中是有用的:与控制代码交错的非均匀(和异步)步骤;但这基本上是一个状态机。

    实际上,Caliburn利用C#编译器获得了一个免费的、自动生成的状态机实现;因此,解决方案可能是构建一个简单的手工状态机,就像C#编译器构建的状态机一样(参见 http://blogs.msdn.com/wesdyer/archive/2007/03/23/all-about-iterators.aspx ).