Ian (Fluxtah) Warwick's blog RSS 2.0
# Tuesday, September 15, 2009

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.

Tuesday, September 15, 2009 3:50:00 AM (GMT Daylight Time, UTC+01:00)  #    Comments [1] -
C#
Sunday, September 20, 2009 9:31:20 AM (GMT Daylight Time, UTC+01:00)
Thanks for the interesting article.

For your second IMessageProvider interface, I would even go into generics and have the callback to act on it, e.g.

public interface IMessageProvider<T>
{
Action<T> ReceiveAction;

and in concrete implementations you can get TextMessageProvider : IMessageProvider<string>
Action<string> ReceiveAction
Hi
Comments are closed.
Archive
<September 2010>
SunMonTueWedThuFriSat
2930311234
567891011
12131415161718
19202122232425
262728293012
3456789
Blogroll
About the author/Disclaimer

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2010
Ian Warwick
Sign In
Statistics
Total Posts: 31
This Year: 2
This Month: 0
This Week: 0
Comments: 4
Themes
Pick a theme:
All Content © 2010, Ian Warwick
DasBlog theme 'Business' created by Christoph De Baene (delarou)