views:

126

answers:

3

Hi, I am trying to get started with some simple dependency injection using C# and i've run up against an issue that I can't seem to come up with an answer for.

I have a class that was written by another department for which I don't have the source in my project. I wanted to inject an object of this type though a constructor using an interface, but of course, i can't change the injected objects implementation to implement the interface to achieve polymorphism when casting the object to the interface type.

Every academic example I have ever seen of this technique has the classes uses classes which are declared in the project itself. How would I go about injecting my dependency without the source being available in the project?

I hope that makes sense, thanks.  

A: 

If you dont have the need to change anything in a class, you hardly need the code. Lets assume you have a class X in a DLL that you wish to inject to another class Y that you are writing. In such a case you can create an instance of X and put as the parameter in the constructor of Y. This will look something like this:

Add a reference to the DLL containing class X in your project.

Use NameSpaceOfX;
Class Y
{
    Public Y() //Default constructor
    {
    }

    Public Y(X instanceOfX)
    {
        //Use instanceOfX here as required
    }
}

In you main code:

//Create instance of X
X instanceOfX = new X();
//Inject it into Y
Y instanceOfY = new Y(instanceOfX);
//Use Y now.
Kangkan
+5  A: 

You could create a wrapper around your target type, so for example, you could have a class they provide:

public class TheirClass
{
  public void DoSomething();
}

With which you can define an interface:

public interface ITheirClass
{
  void DoSomething();
}

And implement that interface on a wrapper class:

public class TheirClassWrapper : TheirClass, ITheirClass
{

}

Or, if the class they provided is sealed, you need to do it slightly differently:

public class TheirClassWrapper : ITheirClass
{
  private TheirClass instance = new TheirClass();

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

Then you can inject that interface instead.

I know in MEF we can export concrete types and have them injected correctly, but I'm not sure about other IoC containers.

Matthew Abbott
This was exactly what I was thinking.
Steven
Adapter Pattern. Good call.
Wix
+1  A: 

The question is, why do you want to inject it as an interface? Is it because the class implements some properties/methods that you'd like to abstract out so it can be substituted, or are you just trying to "force" a marker interface onto it because "we always depend on interfaces, not concrete classes" ? If it's the latter then you're on the wrong path as you'd likely just cast it to the concrete immediately anyway.

Assuming the former of the two I can see two options:

  1. Use inheritance instead. This may or may not be possible depending on the class has been created, but you could inherit from it and substitute your new class for the old one.
  2. Create the interface yourself, with the methods/properties you require and wrap the external concrete class in a class that implements the interface.

For option 2, if you can't inherit, as an example, assuming you only care about one method in the class (we'll call it Method1()) you create a matching interface for it:

public interface IMyNewInterface
{
    void Method1();
}

Then create an implementation of it that takes the concrete class as a dependency (injected by your container as normal) that just calls the concrete class:

public class MyNewClass : IMyNewInterface
{
    private MyConcreteClass _MyConcreteClass;

    public void MyNewClass(MyConcreteClass concreteClass)
    {
        _MyConcreteClass = concreteClass;
    }

    public void Method1()
    {
        _MyConcreteClass.Method1();
    }
}
Steven Robbins
But with the latter of the two options, it would be possible to unit test your own class which uses the 3rd party class as an argument passed to the constructor. i.e it would be possible to mock TheirClass with ITheirClass
David Archer
Both options enable you to substitute theirclass (generics aside), the interface approach would be my preference though.
Steven Robbins
Sorry, I didn't mean options 1 and 2. Was referring to the "..we always depend..." quote. Perhaps I misread. Maybe you meant that it shouldn't be done just for the sake of being done. But good practices means we smooth the way for future changes or maintenance. If the class was injected then it would make it easier to inject it with e.g aop performance measurement??
David Archer
Sure, not saying it's not good practice to depend on interfaces, I just wanted to make sure the poster was aware of *why* we do that and not just doing it because of a "we always use interfaces" comment somewhere. Depending on what the external class is/does would decide for me wither it was worth wrapping or not - as with everything, you have to be pragmatic and engage your brain :-)
Steven Robbins
That was a really great help guys, thanks for that. The whole objective is to allow unit testing and I will be sure to consider wether or not it is worth injecting the class at all rather than blindly injecting everything. Thank you all for your help.
Phil Harris