Whilst working on my network engine I came across a problem that I initially solved with an interface, but it turned out that the class that implemented this interface exposed public methods that I really wanted to be private, an example will explain the problem.
public interface IMessageReceiver
{
void Receive(string message);
}
public interface IMessageProvider
{
IMessageReceiver MessageReceiver;
void Update();
}
public class ConcreteReceiver: IMessageReceiver
{
private IMessageProvider _MessageProvider;
public ConcreteReciever(IMessageProvider messageProvider)
{
_MessageProvider = messageProvider;
_MessageProvider.MessageReceiver = this;
}
public void Receive(string message)
{
Console.WriteLine(message);
}
public void Update()
{
MessageProvider.Update();
}
}
When calling ConcreteReceiver.Update(), this will call MessageProvider.Update(), then, the concrete implementation of IMessageProvider should call IMessageReceiver.Receive, effectively like a callback.
Now the issue in my case was that I did not want the Receive method of ConcreteReceiver to be public, but of course any concrete type that implements an interface must implement those methods as public, after pondering a while I realised the design was actually flawed anyway, what I really wanted was a callback, so I changed my design as follows.
public interface IMessageProvider
{
Action<string> ReceiveAction;
void Update();
}
public class ConcreteReceiver
{
private IMessageProvider _MessageProvider;
public ConcreteReciever(IMessageProvider messageProvider)
{
_MessageProvider = messageProvider;
_MessageProvider.ReceiveAction = Receive;
}
private void Receive(string message)
{
Console.WriteLine(message);
}
public void Update()
{
MessageProvider.Update();
}
}
So now my Receive method on my ConcreteReceiver can be private, since I am now using a generic Action<T> delegate, this prevents my public API exposing methods that are really meant to be only used internally.