0

I'm mucking about with reactive extensions and Iv'e hit a snag that I can't for the life of me work out what the cause is.

If I use a .NET 4 console mode app, where everything is static as follows:

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 is just a test class in my fake DAL class, this is a simple .NET 4 Class library project, the DaftFrog class, is a simple poco with a few fields in, the dal.save method just simply does a console.WriteLine of a field in the DaftFrog object.

Both classes are just simple stand in's for the real things once I get around to making the RX code work.

Anyway, back to the problem, so the code above works fine, and if I do a few

_subject.OnNext(new DaftFrog());

calls, the fake dal class, prints out what I expect and everything works fine...

HOWEVER>....

If I then transport this code as is, to a class library, and then new up that class library from within my "static program" as follows:

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

And then use that class in my program

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

  }
}

Then my project fails to compile.

Specifically it fails on the line:

_subject.Subscribe(RespondToNewData);

in the RxProducer class library, mores the point, the error the compiler throws back makes little sense either:

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

At first I thought that it might have been the static thing, so I made everything in the class library static, and that made no difference at all.

Iv'e really not done much with Rx until now, but I work with C# and VS 99% of the time, so I'm aware that the error is telling me it can't convert a type of some description, I just don't understand why it's telling me that, esp when the code works perfectly in the static program, but not in a class library.

Shawty

UPDATE

Second thoughts, I just know there are going to be those who insist that I post the fakedal and daft frog definitions, even though IMHO they won't be required, but to pacify the hordes of pretenders who will ask here they are :-)

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; }
  }
}
shawty
  • 5,729
  • 2
  • 37
  • 71

2 Answers2

1

Sounds like the compiler is having trouble inferring the Action...might be missing a using statement for the relevant extension method. Alternatively, try either of:

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

Or:

var obs = Observer.Create ( I forget the overload );
_subject.Subscribe( obs);
JerKimball
  • 16,584
  • 3
  • 43
  • 55
  • Try 1 : changing to - _subject.Subscribe((Action)RespondToNewData); resulted in the error changing to - Expected a method with 'void RespondToNewData()' signiture , I noticed there was a generic type version as I was typing, so just going to give that a try, your Observer suggestion... – shawty Apr 07 '13 at 20:19
  • Never reached try 2 for those that are wondering, solved it above :-) – shawty Apr 07 '13 at 20:40
  • I assume you actually meant _subject.Subscribe ((Action) RespondToData); This would fail compile, but hopefully R# would suggest the import of the using statement which is similar to the above solution. Both are pretty much the correct answer tho. :-) – Lee Campbell Apr 08 '13 at 09:55
  • @leecampbell heh - yeah, my accuracy is greatly reduced when I'm answering from my phone :) Also, not to be picky, but my first sentences are "probably missing a using statement", albeit for the wrong reason. – JerKimball Apr 08 '13 at 13:33
  • Impressive that you are answering from a phone. Nice! Living in the future man. – Lee Campbell Apr 08 '13 at 20:52
  • @LeeCampbell I only wish I knew `what bloody key the back tick was` on a swype keypad. :( – JerKimball Apr 08 '13 at 21:18
1

Include using System; into file where you have Producer, this will help to convert RespondToNewData to IObserver<T>.

outcoldman
  • 11,584
  • 2
  • 26
  • 30
  • And the winner is..... that totally fixed it..... any chance you can expand on your answer, I'm curious as to why this is the case :-) Generally when I need an assembly adding in my uses clause, R# will tell me which one it is, but in this case R# didn't have a clue, or any suggestions. – shawty Apr 07 '13 at 20:22
  • by the way, that's just kicked me in the head :-) it's always the simple things... 30+ years in this game and it's still the modern equivelent of a missing " or ( that trips me up :-) – shawty Apr 07 '13 at 20:23
  • You are using method `Subscribe` with `Action` parameter, which is defined in `System` namespace. Compiler is smart and it knows how to convert delegate / method to `Action` ([The difference between implicit and explicit delegate creation](http://stackoverflow.com/questions/863688/the-difference-between-implicit-and-explicit-delegate-creation-with-and-without)), but when you don't specify `System` it just does not know to what it can convert it. This is how I understand this, but I never tried to find the root cause of this issue, maybe I'm not quite right on this. – outcoldman Apr 07 '13 at 20:54
  • well it works for me, and Iv'e not got time to go hunting :-) PS: you just fixed quite a biggy that had me scratching my head for something I'm writing for the lidnug.org website re-design – shawty Apr 07 '13 at 23:35
  • Just a comment; adding the using statement doesn't covert RespondToNewData to an IObservable, it allows the resolution of the Extension method that takes and Action that maps to the RespondToNewData delegate/method. – Lee Campbell Apr 08 '13 at 09:54