4

I have a method that accepts an interface and does type checking on the parameter, and depending upon the type a decision is made to either send an email or an alert

    public void Bar(ISomeInterface someClass)
    {
        if (someClass is SomeClassToo)
        {
            Emailer.Send(someClass.Something());
        }
        else
        {
            Alerter.Alert(someClass.Something());
        }
    }

I know this is bad for obvious reasons, but I would like to know what other options I have to resolve this, as one of the solutions I have is to put an abstraction on each of the classes that implements ISomeInterface for the emailer/alerter using an ICommunicator (see below) but I am not sure that is right as it feels like somewhere in my code there will have to be something that checks the type or knows about each type even if it is just in an IOC container configuration.

public class SomeClass : ISomeInterface
{
    private ICommunicator _communicator;

    public SomeClass(ICommunicator communicator)
    {
        _communicator = communicator;
    }

    public void Something()
    {
        if (_communicator != null)
        {
            _communicator.Send("yee ha");
        }
    }
3

Without the full context it's hard to know the right thing to do.

It seems to me though that the ISomeInterface implementers need to do something differently, depending on the implementation. That leads me to believe that your second approach is correct.

The thing is, each ISomeInterface implementation can have its own list of dependencies. One could take an Alerter while another could take an Emailer. So long as a "third party" class could call ISomeInterface.Something() without needing to know anything about whether Something() is calling an Emailer or an Alerter or a SkynetActivatoryou're set. When SomeClass is constructed, something will need to know which dependencies to provide to it, but that's ok, because it's a concrete class.

Concrete classes are allowed to have dependencies. Interfaces should not be dependent on implementation.

|improve this answer|||||
  • There is no real context other than that it is something that I frequently see in code (and am guilty of doing myself), the example is contrived and only meant to reflect what is discussed in this article codebetter.com/jeremymiller/2006/01/18/… – nickbw Sep 1 '15 at 3:38
  • 3
    In the case of that example, the problem exists because the responsibility for handling the message should be with the IMessageHandler, not with the code that's calling the message handler. Issues like this come down to poor class design and trying to squeeze too much use out of a single interface. – Stephen Sep 1 '15 at 5:11
3

it feels like somewhere in my code there will have to be something that checks the type or knows about each type even if it is just in an IOC container configuration.

The Command Pattern

A nod to @Stephen comment.

The command pattern decouples the "request" from the requestor. Quoting the linked site:

  • encapsulate a request in an object
  • allows the parameterization of clients with different requests
  • allows saving the requests in a queue
|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.