3

I am trying to build a framework of objects where the main actors can be interchanged freely. At the moment I've done this by creating an abstract base class that all of my actors can be derived from. A key reason for using an abstract class over an interface was there there is a very small bit of common code that all of the derived classes should be using.

My goal is to make a system that can be easily extended by other developers (one day) that shares some common logic and the derived objects can be seamlessly interchanged.

I've had a few issues with the way I've designed the system. One being that it hasn't been easy to test consumers of my framework. But the one I'm most interested in solving at the moment is that some of the derived classes need to implement IDisposable because they contain objects which need to be disposed.

The best solution I've found at the moment is to have the abstract class implement IDisposable even though it doesn't require it and some of the other derived classes don't either. I realize I have some fundamental issues with the way I've modelled my objects and I'm trying to work out the best way to do it.

However, I'm still curious what is the best way to conditionally implement IDisposable? Or do I just have a serious design issue that needs to get sorted out instead and I'm trying to solve a problem that will no longer be an issue with the correct model?

  • Shared common code or shared common state? You can do the former with extension methods on an interface – Caleth Apr 19 '16 at 13:41
  • You don't need to conditionally implement IDisposable. Always implement it in the abstract base class (or interface) and have the abstract base class (or whoever needs to) provide a Dispose that does nothing. – Erik Eidt Apr 19 '16 at 14:57
4

I don't think it's unreasonable for your abstract base class to provide an empty implementation of the IDisposable interface, and for subclasses to implement their own implementation as required. That seems to me a commonly used and understood pattern.

| improve this answer | |
  • Downvoted why ? – Brian Agnew Apr 19 '16 at 20:13
  • Because it's much preferable to have a design that doesn't require you to implement interfaces that you're not really implementing. – RubberDuck Apr 19 '16 at 23:52
2

Brian Agnew's suggestion is very much applicable, but I'd like to point out something else:

I get the feeling that maybe the actors (the plugged-in behavior you mentioend) on your model are carrying two very different responsibilities. Alternatively, you could design your framework to have a separate registration mechanism, exclusively for disposable resources, in the same way you allow the actors to be registered. Just to clarify, let's say you currently have the following class:

class MyFramework {
   public void RegisterActor(Actor actor) {
     ...
   }
}

And that the Actor base-class (or interface) looks like this:

abstract class Actor : IDispoable {
   ...
}

You could break apart the notions of actors and disposable resources by changing the usage of your framework to allow both to be registered separately, like so:

class MyFramework {
  public void RegisterActor(Actor actor) {
    ...
  }

  public void RegisterResource(IDisposable resource) {
    ...
  }
}

This would allow you to break the IDisposable interface out of your actor model, while still giving the option to the subclass implementer to have both implementations in the same object, if that makes sense, like so:

class SomeActorImplementation : Actor, IDisposable {
   ...
}

With that, the same object can be sent to both RegisterActor and RegisterResource methods of the framework object, but it will have no knowledge of it.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.