Работи ли Subject.Subscribe само в статичен екземпляр (или пропускам нещо)

Бъркам с реактивни разширения и попаднах на камък, който не мога да разбера каква е причината за живота си.

Ако използвам приложение за конзолен режим .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 Class, класът DaftFrog е прост poco с няколко полета, методът dal.save просто прави конзола.WriteLine of поле в обекта 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 досега, но работя с C# и VS 99% от времето, така че съм наясно, че грешката ми казва, че не може да конвертира тип от някакво описание, просто не Не разбирам защо ми казва това, особено когато кодът работи перфектно в статичната програма, но не и в библиотека от класове.

Шаути

АКТУАЛИЗИРАНЕ

Втори размисъл, просто знам, че ще има хора, които настояват да публикувам определенията за фалшиви и глупави жаби, въпреки че IMHO те няма да са задължителни, но за да успокоят ордите от претенденти, които ще питат, ето ги :-)

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

person shawty    schedule 07.04.2013    source източник


Отговори (2)


Включете using System; във файл, където имате Producer, това ще помогне за конвертирането на RespondToNewData в IObserver<T>.

person outcoldman    schedule 07.04.2013
comment
И победителят е..... това напълно го поправи..... всеки шанс можете да разширите отговора си, любопитен съм защо е така :-) Като цяло, когато имам нужда от сборка, добавяйки в моя използва клауза, R# ще ми каже кой е, но в този случай R# нямаше представа или някакви предложения. - person shawty; 08.04.2013
comment
между другото, това просто ме ритна в главата :-) винаги са прости неща... 30+ години в тази игра и все още е съвременният еквивалент на липсващо или ( това ме спъва :-) - person shawty; 08.04.2013
comment
Вие използвате метод Subscribe с Action<T> параметър, който е дефиниран в System пространство от имена. Компилаторът е умен и знае как да конвертира делегат/метод в Action<T> (Разликата между неявно и изрично създаване на делегат), но когато не посочите System, той просто не знае в какво може да го преобразува. Ето как разбирам това, но никога не съм се опитвал да намеря първопричината за този проблем, може би не съм съвсем прав за това. - person outcoldman; 08.04.2013
comment
добре, работи за мен и нямам време да отида на лов :-) PS: току-що поправихте доста голяма грешка, която ме накара да се почеша по главата за нещо, което пиша за препроектирането на уебсайта lidnug.org - person shawty; 08.04.2013
comment
Само коментар; добавянето на израза using не прикрива RespondToNewData към IObservable‹T›, то позволява разрешаването на метода Extension, който взема и Action‹T›, който се преобразува в делегата/метода RespondToNewData. - person Lee Campbell; 08.04.2013

Звучи сякаш компилаторът има проблеми с извеждането на действието...може да липсва израз за използване за съответния метод на разширение. Като алтернатива опитайте едно от следните:

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

Or:

var obs = Observer.Create ( I forget the overload );
_subject.Subscribe( obs);
person JerKimball    schedule 07.04.2013
comment
Опитайте 1: промяна на - _subject.Subscribe((Action)RespondToNewData); доведе до промяна на грешката на - Очаква се метод с подпис "void RespondToNewData()", забелязах, че има версия с общ тип, докато пишех, така че просто ще опитам това, вашето предложение от наблюдател... - person shawty; 08.04.2013
comment
Никога не стигнах до опит 2 за тези, които се чудят, решен по-горе :-) - person shawty; 08.04.2013
comment
Предполагам, че всъщност сте имали предвид _subject.Subscribe ((Action‹DaftFrog›) RespondToData); Това няма да се компилира, но се надяваме, че R# ще предложи импортирането на израза using, който е подобен на горното решение. И двата са до голяма степен верният отговор. :-) - person Lee Campbell; 08.04.2013
comment
@leecampbell хех - да, точността ми е значително намалена, когато отговарям от телефона си :) Освен това, за да не бъда придирчив, но в първите ми изречения вероятно липсва израз за използване, макар и по грешна причина. - person JerKimball; 08.04.2013
comment
Прави впечатление, че отговаряте от телефон. хубаво! Живеещ в бъдещето човек. - person Lee Campbell; 09.04.2013
comment
@LeeCampbell Иска ми се само да познавам what bloody key the back tick was на swype клавиатура. :( - person JerKimball; 09.04.2013