【问题标题】:Does Subject.Subscribe only work in a static instance (or am I missing something)Subject.Subscribe 是否仅在静态实例中工作(或者我错过了什么)
【发布时间】:2013-04-08 22:10:04
【问题描述】:

我正在处理响应式扩展,我遇到了一个我一生都无法弄清楚原因的障碍。

如果我使用 .NET 4 控制台模式应用程序,其中一切都是静态的,如下所示:

using System;
using System.Reactive.Subjects;
using FakeDal;
using FakeDal.Entites;
using RxProducer;

namespace Runner
{
  class Program
  {
    private static readonly Subject<DaftFrog> _subject = new Subject<DaftFrog>();
    private static readonly Repository<DaftFrog> _frogRepo = new Repository<DaftFrog>();


    static void Main()
    {
      _subject.Subscribe(RespondToNewData);
    }

    private static void RespondToNewData(DaftFrog frog)
    {
      _frogRepo.Save(frog);
    }


  }
}

DaftFrog 只是我的假 DAL 类中的一个测试类,这是一个简单的 .NET 4 类库项目,DaftFrog 类是一个包含几个字段的简单 poco,dal.save 方法只是简单地做一个控制台.WriteLine DaftFrog 对象中的一个字段。

一旦我开始让 RX 代码工作,这两个类都只是真实事物的简单替代品。

无论如何,回到问题,所以上面的代码工作正常,如果我做几个

_subject.OnNext(new DaftFrog());

调用,假 dal 类,打印出我所期望的,一切正常......

但是>....

如果我将这段代码按原样传输到类库,然后从我的“静态程序”中新建该类库,如下所示:

using System.Reactive.Subjects;
using FakeDal;
using FakeDal.Entites;

namespace RxProducer
{
  public class Producer
  {
    private readonly Subject<DaftFrog> _subject = new Subject<DaftFrog>();
    private readonly Repository<DaftFrog> _frogRepo = new Repository<DaftFrog>();

    private int _clock;

    public void Start()
    {
      _subject.Subscribe(RespondToNewData);
    }

    public void Stop()
    {
    }

    public void Tick()
    {
      if(_clock % 5 == 0)
      {
        DaftFrog data = new DaftFrog();
        _subject.OnNext(data);
      }
      _clock++;

    }

    private void RespondToNewData(DaftFrog frog)
    {
      _frogRepo.Save(frog);
    }
  }
}

然后在我的程序中使用那个类

using System;
using RxProducer;

namespace Runner
{
  class Program
  {
    private static readonly Producer _myProducer = new Producer();

    static void Main()
    {
      _myProducer.Start();

      while(!line.Contains("quit"))
      {
        _myProducer.Tick();
        line = Console.ReadLine();
      }

      _myProducer.Stop();
    }

  }
}

然后我的项目编译失败。

具体失败就行了:

_subject.Subscribe(RespondToNewData);

在 RxProducer 类库中,更重要的是,编译器返回的错误也毫无意义:

Error   1   The best overloaded method match for 'System.Reactive.Subjects.Subject<FakeDal.Entites.DaftFrog>.Subscribe(System.IObserver<FakeDal.Entites.DaftFrog>)' has some invalid arguments  H:\programming\rxtesting\RxProducer\Producer.cs 17  7   RxProducer

Error   2   Argument 1: cannot convert from 'method group' to 'System.IObserver<FakeDal.Entites.DaftFrog>'  H:\programming\rxtesting\RxProducer\Producer.cs 17  26  RxProducer

起初我以为它可能是静态的东西,所以我将类库中的所有内容都设置为静态,这没有任何区别。

直到现在我真的没有对 Rx 做太多,但我 99% 的时间都在使用 C# 和 VS,所以我知道错误告诉我它无法转换某种描述的类型,我只是不明白为什么它告诉我,尤其是当代码在静态程序中完美运行时,但在类库中却没有。

肖蒂

更新

第二个想法,我只知道会有人坚持要我发布虚假和愚蠢的青蛙定义,即使恕我直言,它们不是必需的,但为了安抚那些会在这里问他们的伪装者:-)

using System;

namespace FakeDal
{
  public class Repository<T>
  {
    public void Save(T entity)
    {
      Console.WriteLine("Here we write T to the database....");
    }

  }
}

namespace FakeDal.Entites
{
  public class DaftFrog
  {
    public int Id { get; set; }
    public string Name { get; set; }
    public bool IsTotalyDaft { get; set; }
  }
}

【问题讨论】:

    标签: visual-studio-2010 compiler-errors system.reactive


    【解决方案1】:

    using System; 包含到您拥有Producer 的文件中,这将有助于将RespondToNewData 转换为IObserver&lt;T&gt;

    【讨论】:

    • 赢家是......完全解决了它......任何机会你可以扩展你的答案,我很好奇为什么会这样:-)一般当我需要在我的 uses 子句中添加一个程序集时,R# 会告诉我它是哪一个,但在这种情况下,R# 没有任何线索或任何建议。
    • 顺便说一句,这让我很头疼 :-) 它总是简单的事情......在这个游戏中已经有 30 多年了,它仍然是缺失“或”的现代等效项我起来了:-)
    • 您正在使用带有Action&lt;T&gt; 参数的Subscribe 方法,该参数在System 命名空间中定义。编译器很聪明,它知道如何将委托/方法转换为Action&lt;T&gt; (The difference between implicit and explicit delegate creation),但是当您不指定System 时,它只是不知道它可以转换成什么。这就是我的理解,但我从来没有试图找到这个问题的根本原因,也许我不太正确。
    • 它对我有用,而且我没有时间去打猎 :-) PS:你刚刚修复了一个让我为我正在为 lidnug 写的东西而挠头的大问题.org 网站重新设计
    • 只是一个评论;添加 using 语句不会将 RespondToNewData 转换为 IObservable,它允许解析采用的 Extension 方法和映射到 RespondToNewData 委托/方法的 Action
    【解决方案2】:

    听起来编译器在推断动作时遇到了麻烦...可能缺少相关扩展方法的 using 语句。或者,尝试以下任何一种:

    _subject.Subscribe ((Action<DaftFrog>) RespondToData);
    

    或者:

    var obs = Observer.Create ( I forget the overload );
    _subject.Subscribe( obs);
    

    【讨论】:

    • 尝试1:更改为-_subject.Subscribe((Action)RespondToNewData);导致错误更改为 - 期望一个带有 'void RespondToNewData()' 签名的方法,我注意到在我输入时有一个泛型类型版本,所以尝试一下,你的观察者建议......
    • 对于那些想知道的人来说,从来没有尝试过 2,在上面解决了:-)
    • 我假设您实际上是指 _subject.Subscribe ((Action) RespondToData);这将无法编译,但希望 R# 会建议导入类似于上述解决方案的 using 语句。两者几乎都是正确的答案。 :-)
    • @leecampbell heh - 是的,当我通过手机接听电话时,我的准确性大大降低了 :) 另外,不要挑剔,但我的第一句话是“可能缺少使用语句”,尽管出于错误的原因。
    • 令人印象深刻的是,您正在通过电话接听电话。好的!活在未来的人里。
    猜你喜欢
    • 2021-04-17
    • 1970-01-01
    • 1970-01-01
    • 2021-12-20
    • 1970-01-01
    • 2021-08-05
    • 2018-03-02
    • 2020-06-08
    • 1970-01-01
    相关资源
    最近更新 更多