# Using delegates to communicate between forms and networkcommunicator class

I have multiple forms, each of which would like to send message through the network, using my NetworkCommunicator class's SendMessage method.

The solution I described here works, however it is ugly, and bludgeons some of the main concepts of OOP paradigm. What I'm looking for (and I'm open to any suggestions) is basically to achieve the same goal but in a more elegant, and OOP conforming solution. (maybe by events?)

I'm using more than these forms, but for the example, these seemed to be enough.

//using statements
namespace examplespace
{
public delegate void ImprovedSenderDelegate(string message);

{
private  NetworkCommunicator ncom = new NetworkCommunicator();
public Ncom
{
get { return ncom; }
}

{
MainForm mf = new MainForm();
mf.Owner = this;
//other things i do etc.
this.Hide();
mf.Show();
}

public class MainForm :Form
{
public ImprovedSenderDelegate ISD;

{
}

private void I_Want_To_send_A_Message(string message)
{
ISD(string);
}
}//endofMainForm

public class NetworkCommunicator
{
public void SubscribeToSendMessage(object sender)
{
if (sender is MainForm)
{

(sender as MainForm).ISD += new ImprovedSenderDelegate(SendMessage);
}
}

private void SendMessage(string message)
{/*magic*/}
}/endofNetworkCommunicator
}

-
Feel more complex than it should have been. Is it a two-way communication, or do forms send their message in one direction only? Also, I believe that the MainForm should temporarily show the LoginForm, and not what you have - a LoginForm permanently shows the MainForm. I would simplify things as much as possible first. – Leonid Dec 30 '12 at 20:30
Forms send their messages to the server only (through one tcp connection) using delegates however each form can receive message from the server. I Think your idea about the MainForm vs Loginform is quite right, i don't know why i didn't do it that way. – Cyberbird Dec 30 '12 at 21:19
Does the communication need to be truly asynchronous? The LoginForm does not need it. It should spin around and wait until the login succeeds. What about the other form? Give me an example of the type of communication that goes on. – Leonid Dec 30 '12 at 23:17
Well, for the LoginForm it's not entirely necessary, however, other forms work in a manner that they need it. What the server does is, it connects to a device via serial port, and sends everything the device writes there, to the client, and writes everything to the device which the client sends using a basic protocol WRITE_DEVICE|DEVICE_ID|MESSAGE. So because of this, at least some of the client's forms have to work async. Because they have to show the message, the device sends while being able to send messages themselves. Also there could be multiple devices, which i handle on tabbed forms. – Cyberbird Dec 31 '12 at 10:28
Is this a freeware/opensource project? – C Sharper Dec 31 '12 at 11:08

My suggestions:

If the NetworkCommunicator exists only once per application, you should create a singelton. Code sample:

    /// <summary>
/// Provides a base class for singeltons.
/// </summary>
/// <typeparam name="T">The class that act as a singelton.</typeparam>
public abstract class Singleton<T>
where T : class
{
protected Singleton()
{
}

/// <summary>
/// Gets the singelton instance.
/// </summary>
public static T Instance
{
get { return Nested._instance; }
}

private sealed class Nested
{
/// <summary>
/// Creates the nested instance class.
/// </summary>
///
/// <remarks>
/// Explicit static constructor to tell the compiler
//  not to mark type as beforefieldinit.
/// </remarks>
static Nested()
{
ConstructorInfo constructor = typeof (T).GetConstructor(Type.EmptyTypes) ??
typeof(T).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, Type.EmptyTypes, null);

if (constructor == null)
throw new InvalidOperationException("Class has no private nor public constructor");

_instance = (T)constructor.Invoke(null);
}