简体   繁体   中英

Dependency Injection and Explicit Interface Implementation

Is there a benefit implementing interfaces explicitly with respect to Dependency Injection?

As far as I understand, interfaces can be implemented either explicitly or implicitly:

interface IFoo
{
    void Bar();
}

//implicit implementation
class Foo1 : IFoo
{
    public void Bar(){}
}

//explicit implementation
class Foo2 : IFoo
{
    void IFoo.Bar(){}
}

Now the explicit implementation can only be called by calling the interface method, while the implicit implementation can be called directly on an instance of the class:

class Baz
{
    void Ba()
    {
        Foo1 foo1 = new Foo1();
        foo1.Bar();

        Foo2 foo2 = new Foo2();
        foo2.Bar();    //syntax error

        IFoo foo2_explicit = new Foo2();
        foo2_explicit.Bar();
    }
}

Thus, using explicit interface implementations, one cannot accidentally call a method on a concrete class, but one has to call the interface method. Does this prevent tightly coupled code as is one purpose of DI or am I barking up the wrong tree here? After all, one cannot accidently write a constructor or method that gets a concrete class injected instead of an interface:

class Baz
{
    void Ba(Foo2 foo)
    {
        foo.Bar(); //syntax error
    }

    void Bb(IFoo foo)
    {
        foo.Bar();
    }
}

Normally, the purpose of Dependency Injection is decoupling , which you achieve by injecting the abstraction into its client:

public class Baz
{
    private readonly IFoo foo;

    public Baz(IFoo foo)
    {
        this.foo = foo;
    }

    // Members using this.foo go here...
}

This ensures that Baz depends on IFoo , and is decoupled from any concrete implementation.

Whether or not a concrete class implements IFoo implicitly or explicitly makes no difference.

Once in a while, a class may have a Concrete Dependency , but this isn't particularly normal; and when it happens, the concrete dependency is concrete , so often will not implement an interface at all. Explicit versus implicit interface implementation is irrelevant in such cases.

If your class is in container, then you use interface. So, there are no benefits.

But, if you use your class directly (in tests for example) you have to cast to access the method and it is not convenient.

Total: 0 advantages when you use class in container and bad for tests.

In my opinion, in general one should always keep a reference to an object whose type is "just enough" to use. Consider the following example:

public interface IDo
{
    void Do();
}

public interface IWatch
{
    void Watch();
}

public class Foo : IDo, IWatch
{
    public void Dummy() { }

    public void Watch() { }

    public void Do() { }
}

and then:

//I only want to use Do()
IDo aFoo = new Foo();

//I only want to use Watch()
IWatch bFoo = new Foo();

//I want to use stuff from Foo and optionally stuff from IDo or IWatch
Foo cFoo = new Foo();

When it comes to using dependency injection containers like MEF or Unity you should use an interface to export an object into the container and import it with the same interface type.

Following these patterns I don't really see a benefit in using explicit interface implementations. (It also makes locating your implementation methods more difficult in the standard Visual Studio comboboxes above your text editor)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM