4

I have two very similar classes that do essentially the same thing. The only difference is in a callback handler provided to an instance of each class. The callback handlers are different and they are accepted with different parameters. I would like to generalize most of the code from these classes into a base class. Any ideas on how to generalize the delegate code intelligently? I'm on .NET 2.0

Note: I read this very useful blog on inheritance with delegates and articles on covariance and contravariance with delegates, but I still don't see how that knowledge can be applied here.


public class A
{
    public delegate void AHandler(string param1, string param2);
    public void AcceptHandler(string param3, AHandler handler);
    public void InvokeHandler(string forParam1, string forParam2);

    // the rest is same
}

public class B
{
    public delegate void BHandler(int param1);
    public void AcceptHandler(int param2, int param3, int param4, BHandler handler);
    public void InvokeHandler(int forParam1);

    // the rest is same
}

EDIT: "the rest" of the code is exact same, except calls to the delegate methods that have different signatures. Something like this:


public void StartListening()
{
   Timer timer = new Timer(CheckForChanges, null, 0, 1000);            
}

private void CheckForChanges()
{
    // pull changes, and pass different params to InvokeHandler()
}
kateroh
  • 4,382
  • 6
  • 43
  • 62
  • 2
    covariance and contra-variance are very limited until .NET 4.0. That's when the main support of covariance and contra-variance of generic types comes to life – James Michael Hare May 13 '11 at 17:50
  • 3
    Can you add some detail around how the delegate and the handlers are invoked by the mostly-common code? I am thinking about some sort of abstract OnRaise() event defined and called by the base but overriden and impelmented in A and B to do 'the right thing' with the delegate and handlers but I'm not sure without knowning more – n8wrl May 13 '11 at 17:57

1 Answers1

5

Why not set it up like this:
Edit: I've updated to include the methods from your edit.

public abstract class AbstractBase {
    // "the rest"
    public void StartListening() {
        Timer timer = new Timer(CheckForChanges, null, 0, 1000);            
    }
    protected abstract void CheckForChanges();
}

public class A : AbstractBase {
    public delegate void AHandler(string param1, string param2);
    public void AcceptHandler(string param3, AHandler handler);
    public void InvokeHandler(string forParam1, string forParam2);
    protected override void CheckForChanges() {
        //Do stuff for this version of the class
    }
}

public class B : AbstractBase {
    public delegate void BHandler(int param1);
    public void AcceptHandler(int param2, int param3, int param4, BHandler handler);
    public void InvokeHandler(int forParam1);
    protected override void CheckForChanges() {
        //Do stuff for this version of the class
    }
}

This way, you'll have all your code that is the same in a single class, and then the individual classes A and B can have whatever form of the methods you need.

Or are you looking for a way to invoke the delegates generically irrespective of which class?

ie. Something like:

AbstractBase ab = new A();
ab.InvokeDelegate();
  • Yes, that would be nice to generalize delegate code, because "the rest" of the code is the same except when delegate-related stuff is used (see the edit). – kateroh May 13 '11 at 18:41
  • @kateroh - So `StartListening` is the same but `CheckForChanges` depends on the delegate method signatures/invocation? – Richard Marskell - Drackir May 13 '11 at 19:06
  • Yes. The same with other methods in both classes. – kateroh May 13 '11 at 19:09
  • @kateroh - See my edit. I think that should address your edit. – Richard Marskell - Drackir May 13 '11 at 19:12
  • Also, I really recommend checking out this book: [Head First Design Patterns](http://www.amazon.com/First-Design-Patterns-Elisabeth-Freeman/dp/0596007124) It's Java-based but the code examples are simple and usually translate to C# easily. It goes over different design issues exactly like this and outlines tried and tested methods of solving them. It's also easy to read. :) – Richard Marskell - Drackir May 13 '11 at 19:19