Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dependency Injection for concrete .Net classes

What is the preferred way for injecting/isolating classes that are sealed in dlls and do not implement interfaces?

We use Ninject.

Let's say that we have a class "Server" and we want to inject/isolate the class TcpServer which "Server" uses.

Don't want to be too specific because I want to know the best way, but let's say something like that:

public class Server 
{
    IServer _server;
    public Server(IServer server) 
    { 
        _server = server;
    }

    public void DoSomething()
    {
        _server.DoSomething();     
    }
}

_server should be injected with, let's say, TcpClient or mock in case of testing

like image 228
Guy Levin Avatar asked Apr 27 '26 07:04

Guy Levin


1 Answers

If TcpServer is sealed and implements no interfaces, but you still want to decouple a client from its particular implementation, you'll have to define an interface that the client can talk to, as well as an Adapter from TcpServer to the new interface.

It can be tempting to extract an interface from the concrete class, but don't do this. It creates a semantic coupling between the interface and the concrete class, and you'll most like end up breaking the Liskov Substitution Principle.

Instead, define the interface in terms of the what the client needs. This follows from the Dependency Inversion Principle; as APPP, chapter 11 explains: "clients [...] own the abstract interfaces". A Role Interface is best.

So if your client needs a DoSomething method, that's all you add to the interface:

public interface IServer
{
    void DoSomething();
}

You can now inject IServer into your client, using Constructor Injection:

public class Client 
{
    private readonly IServer server;

    public Client(IServer server) 
    {
        if (server == null)
            throw new ArgumentNullException("server");

        this.server = server;
    }

    public void DoFoo()
    {
        this.server.DoSomething();     
    }
}

When it comes to TcpServer, you can create an Adapter over it:

public class TcpServerAdapter : IServer
{
    private readonly TcpServer imp;

    public TcpServerAdapter(TcpServer imp)
    {
        if (imp == null)
            throw new ArgumentNullException("imp");

        this.imp = imp;
    }

    public void DoSomething()
    {
        this.imp.DoWhatever();
    }
}

Notice that the methods don't have to have the same names (or even exact same signatures) in order to be adapted.

like image 181
Mark Seemann Avatar answered Apr 28 '26 22:04

Mark Seemann



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!