A while ago I was having a discussion with one of my fellow developers at EMC Consulting about SharePoint and getting dependency injection working with it. Well finally after a few weeks I have found the time to produce a quick example of just how easy it is to get dependency injection working in SharePoint using a great tool called Ninject. You can find additional information about Ninject at http://ninject.org/. So this get started!
First off Ninject works by providing you with something it calls a kernel which it uses for returning an instance of a specific type. You can think about the kernel as a big brother to the factory pattern we all know and love. Because the kernel is so important the first things you need to do to get Ninject working in SharePoint is create an instance of a kernel and a simple way to do this in SharePoint is through the use of a HttpModule.
As you can see from the code the module is very simple and straightforward and all it does is create an instance of the kernel and sets it's bindings so Ninject knows which instance of a type to return when a request for “IWarrior” or “IWeapon” is made. Remember that you will need to add an entry to the “httpModules” section of your web.config (see below) which in a real world application would be done using the SPWebConfigModification class. However, as this is just a demo I have added it by hand to save myself sometime.
Now to allow Ninject to actually do it's dependency injection magic there are a few things you must do. The first of these is to modify the “AssemblyInfo.cs” file for all of your projects (well the ones using Ninject at least) so they will allow partially trusted callers. If you don't do this then a security exception is thrown when you inject your object into the Ninject kernel.
The next thing you need to do is inject the actual instance of the object you want Ninject to apply dependency injection to into the kernel you created. The way I did this was to create a number of base classes which inherit from commonly used items in SharePoint like Web Parts, User Controls and Application Pages. Then within the constructor for each base class I inject the instance of that object into the Ninject kernel.
This is the web part base class:
This is the application page base class:
And finally the user control base class:
You can see all the bases classes shown below in the “Blog.IOC” project.
Once you have done this Ninject will work and happily inject any dependencies you have marked up with the “[Inject]” attribute into your objects.
So does this all work you ask? Well yes indeed it does and to prove it below is the code for a very simple application page which inherits off “LayoutsBase” and a screen shot of it’s rendered output.
[ Notice the use of the inject attribute on the Warrior property so Ninject knows this is something it is responsible for ]
[ The fully rendered output ]
The full source code for the dependency injection example using Ninject can be download from: http://cid-468e9f9e14e99f80.skydrive.live.com/self.aspx/.Public/Blog.IOC.zip
PS. In order to get all this working you will need Visual Studio 2008, WSPBuilder and SharePoint 2007 enjoy :-)
First off Ninject works by providing you with something it calls a kernel which it uses for returning an instance of a specific type. You can think about the kernel as a big brother to the factory pattern we all know and love. Because the kernel is so important the first things you need to do to get Ninject working in SharePoint is create an instance of a kernel and a simple way to do this in SharePoint is through the use of a HttpModule.
1: public class SharePointNinjectHttpModule: IHttpModule, IDisposable2: {3: private readonly HttpApplication _httpApplication;4:5: public void Init(HttpApplication context)6: {7: if (context == null)8: throw new ArgumentException("context");9:10: if(FrameworkHelper.Kernel == null)11: {12: FrameworkHelper.Kernel = GetKernel();13: }14: }15:16: public void Dispose()17: {18: if(_httpApplication == null) return;19: _httpApplication.Dispose();20: }21:22: #region Private methods23:24: /// <summary>
25: /// Gets the kernel.
26: /// </summary>
27: /// <returns></returns>
28: private static IKernel GetKernel()29: {30: IKernel result = new StandardKernel();
31: result.Bind<IWarrior>().To<Samurai>();32: result.Bind<IWeapon>().To<Sword>();33: return result;
34: }35:36: #endregion37: }
As you can see from the code the module is very simple and straightforward and all it does is create an instance of the kernel and sets it's bindings so Ninject knows which instance of a type to return when a request for “IWarrior” or “IWeapon” is made. Remember that you will need to add an entry to the “httpModules” section of your web.config (see below) which in a real world application would be done using the SPWebConfigModification class. However, as this is just a demo I have added it by hand to save myself sometime.
1: <add name="SharePointNinjectHttpModule" type="Blog.IOC.Source.HttpModules.SharePointNinjectHttpModule,Blog.IOC, Version=1.0.0.0, Culture=neutral, PublicKeyToken=bf2ebb07a9bc44ba" />
Now to allow Ninject to actually do it's dependency injection magic there are a few things you must do. The first of these is to modify the “AssemblyInfo.cs” file for all of your projects (well the ones using Ninject at least) so they will allow partially trusted callers. If you don't do this then a security exception is thrown when you inject your object into the Ninject kernel.
1: using System.Security;
2:3: [assembly: AllowPartiallyTrustedCallers]
The next thing you need to do is inject the actual instance of the object you want Ninject to apply dependency injection to into the kernel you created. The way I did this was to create a number of base classes which inherit from commonly used items in SharePoint like Web Parts, User Controls and Application Pages. Then within the constructor for each base class I inject the instance of that object into the Ninject kernel.
This is the web part base class:
1: public abstract class WebPartBase : Microsoft.SharePoint.WebPartPages.WebPart2: {3: protected WebPartBase()
4: {5: FrameworkHelper.Kernel.Inject(this);
6: }7: }
This is the application page base class:
1: public class LayoutsBase : LayoutsPageBase2: {3: protected LayoutsBase()
4: {5: FrameworkHelper.Kernel.Inject(this);
6: }7: }
And finally the user control base class:
1: public abstract class UserControlBase : UserControl2: {3: protected UserControlBase()
4: {5: FrameworkHelper.Kernel.Inject(this);
6: }7: }
You can see all the bases classes shown below in the “Blog.IOC” project.
Once you have done this Ninject will work and happily inject any dependencies you have marked up with the “[Inject]” attribute into your objects.
1: [Inject]2: public IWarrior Warrior { get; set; }
So does this all work you ask? Well yes indeed it does and to prove it below is the code for a very simple application page which inherits off “LayoutsBase” and a screen shot of it’s rendered output.
[ Notice the use of the inject attribute on the Warrior property so Ninject knows this is something it is responsible for ]
1: public class BlogCustomApplicationPage : LayoutsBase2: {3: protected Literal litWarrior;
4:5: [Inject]6: public IWarrior Warrior { get; set; }7:8: protected override void OnLoad(EventArgs e)9: {10: base.OnLoad(e);
11:12: SetUpWarrior();13: }14:15: private void SetUpWarrior()16: {17: litWarrior.Text = Warrior.Name;18: }19: }
[ The fully rendered output ]
The full source code for the dependency injection example using Ninject can be download from: http://cid-468e9f9e14e99f80.skydrive.live.com/self.aspx/.Public/Blog.IOC.zip
PS. In order to get all this working you will need Visual Studio 2008, WSPBuilder and SharePoint 2007 enjoy :-)
Comments
Post a Comment