0

main

class Program
{
    static void Main(string[] args)
    {
        Worker worker = new Worker();
        worker.Start();

        Console.ReadLine();
    }
}

Worker class

    public Worker()
    {

    }

    public Navigator Navigator;
    public Scraper Scraper;

    public void ResetVariables()
    {
        Navigator = new Navigator(this);
        Scraper = new Scraper(this);
    }

    public void Start()
    {
        ResetVariables();
        Navigator.SetHtml();
    }

Navigator class

    private Worker Worker;
    private Scraper Scraper;

    public string Html;

    public Navigator()
    {

    }

    public Navigator(Worker worker)
    {
        Worker = worker;
        Scraper = worker.Scraper;
    }

    public void SetHtml()
    {
        Html = "navigator has changed its html";
        Scraper.ReadHtmlFromNavigator(); //CAUSES NULL REFERENCE IF CALLED INISIDE THIS METHOD
    }

Scraper class

    private Worker Worker;
    private Navigator Navigator;

    public Scraper()
    {

    }

    public Scraper(Worker worker)
    {
        Worker = worker;
        Navigator = Worker.Navigator;
    }

    public void ReadHtmlFromNavigator()
    {
        Console.WriteLine("scraper reading html from navigator: " + Navigator.Html);
    }

When i call Scraper.ReadHtmlFromNavigator() from inside the navigator itself i get a null reference, but if i call it from the worker class it works fine:

public void Start()
    {
        ResetVariables();
        Navigator.SetHtml();
        Scraper.ReadHtmlFromNavigator();
    }

and i get the output:

scraper reading html from navigator: navigator has changed its html
Joao Vitor
  • 169
  • 1
  • 9

2 Answers2

0

Quick answer - Do not store reference to Navigator inside Scrapper and do not store reference to Scrapper inside Navigator. Use reference to Worker instead.

In the method SetHtml call Worker.Scraper.ReadHtmlFromNavigator() instead of Scraper.ReadHtmlFromNavigator()

UPDATE: If you don't want to type Woker.XXX every time, you may create some shortcuts:

private Navigator Navigator { get { return Worker.Navigator; } }
private Navigator Scrapper{ get { return Worker.Scrapper; } }
opewix
  • 4,680
  • 1
  • 15
  • 41
  • True, i was doing that before but was looking for a way to not type Worker everytime i needed things from other classes, but anyways i was not really bothered by that as it still seemed clean. – Joao Vitor Jul 16 '17 at 16:42
  • @JoaoVitor see update in my answer how to create shortcuts – opewix Jul 16 '17 at 16:45
0

You are first constructing a new navigator before you have a scraper:

public void ResetVariables()
{
    Navigator = new Navigator(this);
    Scraper = new Scraper(this);
}

So your navigator constructor sets its scraper variable to a worker.scraper that is not there yet.

Simpy change the order and you should be fine:

public void ResetVariables()
{
    Scraper = new Scraper(this);
    Navigator = new Navigator(this);
}

In general, though, rethink how you set up your application. This kind of undocumented obligatory sequences create problems and are a code smell.

oerkelens
  • 4,600
  • 1
  • 19
  • 28
  • yeah i did that as a solution but yes it seems ugly, so i thought of having a "SetInitialReferences()" method in the Navigator and Scraper and then setting those references there after constructing the classes. – Joao Vitor Jul 16 '17 at 16:42