Ryan LanciauxNew Media Mercenary

Real Ultimate Power : Dependency Injection with Ninject

March 26, 2008 by ryan
Ninja
UPDATE: Nate Kohari (the author of Ninject) posted some excellent information in the comments (enough info that it could probably be a post on its own).

Recently Scott Hanselman compiled a list of Dependency Injection frameworks for .NET. I really didn't plan on trying anything new but Ninject really jumped out at me (honestly, it was more the reference to ninjas than anything). After seeing a couple examples, I thought I would check it out in a bit more detail.

Disclaimer: I've been playing around with Ninject for all of about 3 hours now ... it's very possible there's a better way to do some of this stuff :) So I would really appreciate any feedback.

On to the code

Okay, for this very contrived example we're going to be building car objects out of just an engine and a drive type (extremely accurate I know). Just like in my StructureMap example, I'm going to start by creating the interfaces followed by a default class that we're going to use as our skeleton car ... the interfaces are pretty basic so no need to spend too much time on them.

    public interface IDriveType

    {

        string DriveType{ get;}

    }

 

    public interface IEngine

    {

        string EngineType { get; }

    }



Both of the interfaces have only one string property that will be used for output. A little on the basic side but hey, we're looking at IoC not an accurate car construction. Next we're going to add all our implementations of the Engine

    class FourCylinder : IEngine

    {

        public string EngineType

        {

            get { return "4-Cylinder"; }

        }

    }

 

    class Rotary : IEngine

    {

        public string EngineType

        {

            get { return "Rotary"; }

        }

    }

 

    class SixCylinder : IEngine

    {

        public string EngineType

        {

            get { return "6-Cylinder"; }

        }

    }



And the drive type implementations...

    public class RWD : IDriveType

    {

        public string DriveType

        {

            get { return "Rear Wheel Drive"; }

        }

    }

 

    class FourWD : IDriveType

    {

        public string DriveType

        {

            get { return "Four Wheel Drive"; }

        }

    }

 

    class FWD : IDriveType

    {

        public string DriveType

        {

            get { return "Front wheel drive"; }

        }

    }



And finally the class we're going to use as our base car.

    public class BaseAuto

    {

        private IDriveType _driveType;

        private IEngine _engine;

 

        public string DriveType

        {

            get { return _driveType.DriveType; }

        }

 

        public string Engine

        {

            get { return _engine.EngineType; }

        }

 

        [Inject]

        public BaseAuto(IDriveType drive, IEngine engine)

        {

            _driveType = drive;

            _engine = engine;

        }

    }



You'll notice the [Inject] attribute above our constructor. This is basically telling Ninject to toss in an implementation of the IDriveType and IEngine interfaces to this constructor (more on  Constructor Injection over here).

Now we're on to the fun stuff. Ninject does not use XML to configure injections. Instead we're going to use a class called Module to define all that. As the documentation says, this class should implement IModule but thankfully (at least for the sake of testing), there's a pre-defined base implementation called StandardModule that we can extend.

    public class BaseModule : StandardModule

    {

        public override void Load()

        {

            Bind<IEngine>().To<Rotary>();

            Bind<IDriveType>().To<RWD>();

        }

    }



In the module definition, we're basically saying when we request an object from the Kernel (more on that in a sec.) we want the Rotary class in place of IEngine and the RWD instead of IDriveType. Simple enough, now lets take a look at the Kernel definition / initial code (I'm using winforms for the sake of example but you can really go w/ whatever project type you'd like). A lot of thought went into the naming of the form.

    public partial class Form1 : Form

    {

        private BaseAuto _rx8;

 

        public Form1()

        {

            InitializeComponent();

 

            IKernel kernel = new StandardKernel(new BaseModule());

 

            _rx8 = new BaseAuto(

                kernel.Get<Auto.IDriveType>(),

                kernel.Get<Auto.IEngine>()

                );

 

            MessageBox.Show("RX8: \n Drive Type: " + _rx8.DriveType +

                "\n Engine:" + _rx8.Engine);

        }

    }



And when we run it...



Just what we expected! Lets make things a little more interesting ... Say we wanted to add some other cars to our application? We probably don't want everything to be a rear-wheel drive rotary (Unless you really like RX-8's -- in that case you can buy my RX8 *shameless plug*). Anyways, we're going to accomplish this by changing up our Module a bit to bind to a different IEngine / IDriveType implementation depending on the context.

    public class BaseModule : StandardModule

    {

        public override void Load()

        {

            Bind<IEngine>().To<Rotary>()

                .Only(When.Context.Variable("carType").EqualTo("RX8"));           

            Bind<IDriveType>().To<RWD>()

                .Only(When.Context.Variable("carType").EqualTo("RX8"));

 

            Bind<IEngine>().To<SixCylinder>()

                .Only(When.Context.Variable("carType").EqualTo("Jetta"));

            Bind<IDriveType>().To<FWD>()

                .Only(When.Context.Variable("carType").EqualTo("Jetta"));

 

            Bind<IEngine>().To<FourCylinder>()

                .Only(When.Context.Variable("carType").EqualTo("WRX"));

            Bind<IDriveType>().To<FourWD>()

                .Only(When.Context.Variable("carType").EqualTo("WRX"));

        }

    }



Not too bad right? I mean, just looking at the code we can pretty much tell what's going on due to the Fluent Interface goodness. We can perform more powerful comparisons on our context variable but for now, this will work. Next we need to set up our context in the core part of our application
(where we're instantiating and requesting classes from our Kernel).

        public Form1()

        {

            InitializeComponent();

 

 

            IKernel kernel = new StandardKernel(new BaseModule());

 

            _rx8 = new BaseAuto(

                    kernel.Get<Auto.IDriveType>(

                    With.Parameters.ContextVariable("carType", "RX8")

                ),

                kernel.Get<Auto.IEngine>(

                    With.Parameters.ContextVariable("carType", "RX8")

                )

            );

 

            _jetta = new BaseAuto(

                    kernel.Get<Auto.IDriveType>(

                    With.Parameters.ContextVariable("carType", "Jetta")

                ),

                kernel.Get<Auto.IEngine>(

                    With.Parameters.ContextVariable("carType", "Jetta")

                )

            );

 

 

            _wrx = new BaseAuto(

                    kernel.Get<Auto.IDriveType>(

                    With.Parameters.ContextVariable("carType", "WRX")

                ),

                kernel.Get<Auto.IEngine>(

                    With.Parameters.ContextVariable("carType", "WRX")

                )

            );

 

        }



I've added some buttons so we don't get spammed with message boxes on form load... if we fire this off and click on the various buttons, we see we're getting the expected results!


All in all, I'm liking Ninject for more than just the name -- I can definitely see myself using this in small to medium sized apps. Please let me know what you think...

More info on Ninject:


kick it on DotNetKicks.com




Styles disappear in BlogEngine.NET

March 19, 2008 by ryan

If you have ever had your site running on BlogEngine.NET end up looking like this screenshot -- try disabling the 'Trim Stylesheets' checkbox under the 'Advanced Settings'. From what it looks like, this may be related running BlogEngine.NET in a shared environment or medium trust (here for more info).

kick it on DotNetKicks.com  


Tags:
Categories: General
Actions: E-mail | Kick it! | Permalink | commentComments (1) | RSS comment feedComment RSS


IE8, Microsoft and the Reverse Fanboys

March 8, 2008 by ryan

Here we go again...

As the beta test of IE8 recently became available we are quickly approaching the release of another version of Internet Explorer. To the millions of web designers / developers out there, this can be a troubling time. Much frustration has been expressed about some of the issues (or supposed issues ) in this beta. Some of this concern is definitely understandable -- I mean, IE6 has been the bane of most web developers lives since it was released in 2001. However, I think some of the negativity is present just because it's a Microsoft product.


The Fanboy

The attitude of hating every Microsoft product just because it's Microsoft is something I would call reverse fanboyism. 

"Fanboy (sometimes spelt fanboi) is a term used to describe an individual who is devoted to a single fannish subject, or to a single point of view within that subject, often to the point where it is considered an obsession. Fanboys remain loyal to their particular obsession." wiki

A reverse fanboy, is well, obviously the opposite -- someone who obsessively remains disloyal or passionately against a product.. no matter the circumstances. This mindset is just getting kind of old. I would completely agree about IE6 and IE7 showing little regard for web standards and being an overall headache to develop with, HOWEVER, Microsoft seems to be on a different path this time.


Your Perspective

When I was in elementary school, we would grade each other's writing assignments. The teacher would always tell us to give each other constructive criticism because an outside influence can give additional perspective or show errors that we previously didn't know existed. I hope we can take that same approach here. IE8 is still in beta test -- It is far from being a release ready product and there are still a number of issues. That being said, there are ways that those in the web development community can voice those concerns. It is important to make the IE8 developers aware of the issues as they come up so we don't have to live with the problems when IE8 is released.

 

How's it going to turn out?

Although it has a long way to go, IE8 is leaps and bounds better than its predecessors. I don't know that I will switch from Firefox but from a development standpoint, a standards compliant Internet Explorer seems like a dream come true (although we will probably need to support IE6 for who knows how long). I say we give the IE8 team a chance to fix the bugs (and voice issues as they become apparent) and see what comes out of it. What are your thoughts?

  kick it on DotNetKicks.com




PowerCommands for Visual Studio 2008 -- Weird Side Effect

March 5, 2008 by ryan

Last week, PowerCommands for Visual Studio 2008 was released. The plug-in adds lots of time-saving enhancements to Visual Studio. Unfortunately, there appears to be a weird side-effect when building Outlook plug-ins (and possibly some other project types). Visual Studio would close unexpectedly without any warning or error message. Tracking it back to to the PowerCommands plug-in was difficult, however, this MSDN forum posting pointed me in the right direction. Upon removing PowerCommands, everything worked well again. It appears people have had similar experiences with other project types as well. Hopefully there will be a fix soon and I can begin using it again Smile. Maybe this will save someone a bit of headache.

  kick it on DotNetKicks.com








© 2008 Ryan Lanciaux :: powered by BlogEngine.NET