Good morning!
Yesterday I watched Tekpub's amazing video "Dependency Injection and Inversion of Control" and it blew my mind. I feel like this is how I should be writing code. I have watched it before and even experimented with Ninject a little bit, but feel like I need some more examples of code being refactored into this paradigm.
The brief MUD example he goes into is great, but does anyone know of a site or project where they start with some ugly, but working, code and then refactor it into clean Dependency Injected code?
While I can find examples of code that use Dependency Injection pretty easily, I am having a hard time finding before/after code and I feel like this would greatly help me start programming "at the next level". I need a few more examples to really wrap my head around it.
The Dependency Injection pattern is a particular implementation of Inversion of Control. Inversion of Control (IoC) means that objects do not create other objects on which they rely to do their work. Instead, they get the objects that they need from an outside source (for example, an xml configuration file).
Dependency Injection is an implementation of "Inversion of Control". Inversion of Control (IoC) says that the objects do not create other objects on which they rely to do their work; instead, they get the objects that they need from an outside source (for example, an XML configuration file).
Although dependency injection (DI) isn't built into ASP.NET MVC or Web API, many apps enable it by adding a NuGet package with an inversion of control (IOC) container. These are sometimes referred to as DI containers, for dependency injection (or inversion).
Suppose you wanted to implement a spelling correction service. Input a word/phrase and out pops a corrected version of the word/phrase. What if you were depending on a large, online provider that went down for a day. Ideally, you would implement a backup in case the request to said provider failed. In that backup, you might call your secondary service and hope they're online. Maybe in a last ditch effort in the event they're both down, you implement an offline provider to correct spelling based on a local dictionary that exists on the file system.
How do you manage multiple providers like this?
public class SpellCheck
{
public string FixText(string text)
{
string CorrectedText = string.Empty;
// create HTTP request to Online Provider #1
// return CorrectedText;
}
}
public class SpellCheck
{
private readonly IOnlineSpellService _onlineSpell;
private readonly IOfflineSpellService _offlineSpell;
public SpellCheck(IOnlineSpellService onlineSpell,
IOfflineSpellService offlineSpell)
{
this._onlineSpell = onlineSpell;
this._offlineSpell = offlineSpell;
}
// same method as before, just a slightly different implementation
public string FixText(string text)
{
string fixedText = _onlineSpell.FixText(text);
if(_onlineSpell.Failed)
fixedText = _offlineSpell.FixText(text);
return fixedText;
}
}
Of course, you'd need to implement the interface ISpellOnlineService
(and similar interface for ISpellOfflineService
public interface ISpellOnlineService
{
public bool Failed { get; set; }
public string FixText(string text);
}
Next, implement your spelling providers (both online and offline, or even multiple instances of both to gain more flexibility)
public class OnlineProviderNo1 : IOnlineSpellService
{
public string FixText(string text)
{
// implement online logic
this.Failed = false;
}
}
Finally, register your services by overriding the CreateKernel
method and subclassing your MvcApplication from NinjectHttpApplication
. And apparently with Ninject you replace Application_Start
with an override called OnApplicationStarted
like so:
**This done in global.asax
public class MvcApplication : NinjectHttpApplication
{
// ...
protected override void OnApplicationStarted()
{
base.OnApplicationStarted();
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
protected override IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<IOnlineSpellService>().To<OnlineProviderNo1>();
kernel.Bind<IOfflineSpellService>().To<OfflineProviderNoX>();
return kernel;
}
}
Yes, this is a real world example, as I've implemented it (I actually used Castle Windsor, but it's the identical concept with Ninject--just adapted above) with 3 online providers and 2 offline providers. In CreateKernel
you may choose to include logic to examine a database, config file, etc to determine which provider to register. For example, maybe one service has announced 24 hours of downtime (hopefully, you're lucky enough to have that announced!) so during that time you want to switch to another online provider for which you've implemented an instance of IOnlineSpellService
The MVC StoreFront series covers dependency injection using StructureMap. The project starts off without IoC and adds it later on in episode #13: ASP.NET MVC Storefront Part 13: Dependency Injection
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