I am struggling for last two days to get a grip of DI.
I have two problems:
In my example I have many class instance created under writefile, so should I move out all object creation from there? What if I have a layered design? Should these classes be passed all along?
public interface IWriteFile
{
void write();
}
public class WriteXMLFile : IWriteFile
{
public void write()
{
}
}
public class writefile
{
IWriteFile _file;
public writefile(IWriteFile file)
{
_file = file;
}
public void WriteMyFile()
{
_file.write();
}
}
Let's say you want to test something that uses your abstract class. If you're directly using an abstract class, then if you want to do something different in the shared functionality in the common class, there's not much you can do.
With an interface, you've broken the coupling with the dependency. This is what the Dependency Inversion Principle in SOLID is talking about when it says "High-level modules should not depend on low-level modules. Both should depend on abstractions". Your class shouldn't depend on the lower-level class (even if it's an abstract class) to get its work done. Both the lower-level and higher-level class should depend on the interface which defines how they are going to interact. Using an interface helps separate the two, giving you loose coupling. Something else can handle wiring them together.
Powerful DI frameworks actually handle a lot of this complexity for you.
Let's say you have a class - Thing
- that has a bunch of dependencies.
public Thing(
IThingRepository repository,
IEmailer emailer,
ILogger logger,
INeedMoreStuff stuff
) : IThing
When you set up your IoC container, you'd do something like the following to associate which implementation to use for each interface:
IoC.Register<MySqlThingRepository>().As<IThingRepository>();
IoC.Register<MicrosoftExchangeEmailer>().As<IEmailer>();
IoC.Register<TruncatingFileLogger>().As<ILogger>();
IoC.Register<MoreStuff>().As<INeedMoreStuff>();
IoC.Register<Thing>().As<IThing>();
Then you can simply do:
IThing thing = IoC.Resolve<IThing>();
These fancy frameworks handle getting all the dependencies for you (since you told it how to get them) and will construct a Thing
for you.
That being said, sometimes a fancy framework like that is overkill. In those cases, I usually use the factory pattern to abstract out the details of creating an object while still making sure the object being created follows good DI principles like constructor injection of its dependencies.
Someone described polymorphism as simply "Same interface, different implementation. Substitutability". Wikipedia defines it as "the provision of a single interface to entities of different types". According to those definitions, I think using interfaces doesn't go against polymorphism. I feel in C# interfaces are usually sufficient for providing different implementations of the same "interface".
Yes, you can use an abstract base class to do the same thing, but I'd only use that if there's a common set of functionality I can factor out into the base class to keep my code DRY.
I don't how StructureMap handles this, but presumably there's some logic that will decide when you want to use Thing1
versus Things2
. You might be able to provide a delegate to StructureMap that it can use to get an IThing
which would contain that logic.
Alternatively, you can have a factory that takes some parameters and decides which IThing
to return. There are situations where I've put an interface on my factory and constructor injected that, or alternatively have the factory creating the object using IThing
use the ThingFactory
to get the right one.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With