Home > OS >  Circular Dependecies
Circular Dependecies

Time:02-06

I recently started learning C# to start doing a project of mine. I ran into a problem, where i have to Classes dependent on each other. I have a class called MQTT_Handler which handles everything related MQTT and a Winforms class. The problem is that I need both classes to work with each other. So to control the Form class from the MQTT_class I passed over the Form instance to the constructor of the MQTT_class and delegated some methods, which works so far.

Now I have the problem that I also want send some messages over MQTT from the Form class. There is my problem.

I start everything from Program.cs which looks like this:

static void Main()
{
    ApplicationConfiguration.Initialize();

    UI UIInstance = new UI();
    MQTT_Handler mqtt_handler = new MQTT_Handler(UIInstance);
    mqtt_handler.MQTT_Client();
    Application.Run(UIInstance);
}

Now what I wanted to do is just passing the matt_handler instance over to UI. But doing that would obviously create a circular dependency. Is there any way of passing an instance to a class after it has been created?

This is my MQTT class:

class MQTT_Handler
{
    private UI UIInstance;

    // Constructor
    public MQTT_Handler(UI formInstance)
    {
        UIInstance = formInstance;
        DelegateMethod = new changeLabelDelegate(UIInstance.change_labelMethod);
        MQTT_Client();
    }
}

And UI:

public partial class UI : Form
{
    public delegate void changeLabelDelegate(string text);
    
    //Constructor
    public UI()
    {
        InitializeComponent();
    }
}

CodePudding user response:

The most obvious solution (to me) is to make the UI dependent on the MQTT handler. This handler should not need any knowledge about the UI.

This can be accomplished in several ways. Two examples:

Make DelegateMethod a property of MQTT_Handler and give it a suitable value when UI is instantiated:

    class MQTT_Handler
    {
       public Action<string> DelegateMethod {get;set;}

       // Constructor
       public MQTT_Handler()
       {
           DelegateMethod = (s) => {;};
           MQTT_Client();
       }
    }

And UI:

public partial class UI : Form
{
    private MQTT_Handler _handler;       
    

    //Constructor
    public UI(MQTT_Handler handler)
    {
        InitializeComponent();
        _handler = handler; 
        _handler.DelegateMethod = change_labelMethod;
    }
} 

The second examples uses an event in the `MQTT-Handler' to notify the UI that the label needs changing (this is something of a variation on the same theme as the first example):

    class MQTT_Handler
    {
       private Action<string> DelegateMethod;

       public event? Action<string> MqttValueChanged;

       // Constructor
       public MQTT_Handler()
       {
           DelegateMethod = (s) => MqttValueChanged?.Invoke(s);
           MQTT_Client();
       }
    }

And UI:

public partial class UI : Form
{
    private MQTT_Handler _handler;       
    
    //Constructor
    public UI(MQTT_Handler handler)
    {
        InitializeComponent();
        _handler = handler; 
        _handler.MqttValueChanged  = change_labelMethod;
    }
} 

Note: this second example can obviously be optimised by removing DelegateMethod in MQTT_handler and invoking the event directly wherever you would call DelegateMethod.

  • Related