1

I'm a beginner on IoC and dependency injection. I'm reading about it, but I just can't get it. While I figure out how stuff works, I'm trying to implement some of these patterns on my project (and maybe learn by trial and error).

I'm implementing security control by using FluentSecurity package (from NuGet, btw). I need to implement a Policy Violation Handler, as described on this wiki. The problem is that the example is written for StructureMap IoC-container, and I'm using (or trying to) Ninject 2.2 (it seemed more simple for a beginner).

On their code, they suggest (a):

configuration.ResolveServicesUsing(type => ObjectFactory.GetAllInstances(type).Cast<object>());

And then (b):

public class WebRegistry : Registry
{
    public WebRegistry()
    {
        Scan(scan =>
        {
            scan.TheCallingAssembly();
            scan.AddAllTypesOf<IPolicyViolationHandler>();
        });
    }
}

My concerns:

  1. I know that code (a) will be included on Global.asax. But what is Ninject's alternative to ObjectFactory.GetAllInstances()?
  2. I have no idea neither where this code should be inserted nor what are the equivalents for WebRegistry, Scan, and the internal functions TheCallingAssembly and AddAllTypesOf.

I know this is a bit extensive question, but I appreciate any help! Thanks in advance.

Tieson T.
  • 20,774
  • 6
  • 77
  • 92
tyron
  • 3,715
  • 1
  • 22
  • 36

3 Answers3

3

Marius Schulz has written an excellent article that should help anyone wanting to use Ninject together with FluentSecurity.

Setting Up FluentSecurity to Use Ninject for Dependency Resolution

Tieson T.
  • 20,774
  • 6
  • 77
  • 92
Kristoffer Ahl
  • 1,661
  • 2
  • 18
  • 36
1

I think this would be roughly equivelent

//add an instance of IKernel to your MvcApplication
[Inject]
public IKernel Kernel { get; set; }
...
configuration.ResolveServicesUsing(type => Kernel.GetAll(type));

To get the ability to scan an assembly for dependencies you would need an extension for ninject called Ninject.Extensions.Conventions, which was modeled after the one from SM.

public class WebModule : NinjectModule
{
    public WebModule()
    {
        Kernel.Scan(a => {
                    a.FromAssemblyContaining<YourType>();
                    a.BindWithDefaultConventions();
                    a.InTransientScope();
                });
    }
}

The assembly scanning business obviously isn't strictly necassary for what you're doing, this would work just as well. Personally I'm not a fan of assembly scanning because it seems a little too "magic", and when it doesn't work, it's not fun to debug.

Kernel.Bind<YourType>().ToSelf();
Brook
  • 5,949
  • 3
  • 31
  • 45
  • The NinjectModule part seems fine. But I still got some issues with the "ResolveServicesUsing". I guess the main difficulty here is the fact that originally, ObjectFactory (from SM) is a static class (or only the method is static, whatever), but inside of Global.asax I don't know what is "kernel". – tyron Nov 18 '11 at 14:51
  • Ah, that's easy enough to fix, but it depends on how you're bootstrapping Ninject. Are you using the "WebActivator" method or the "Inherit NinjectAppliction" method? Hint: if you have App_Start/NinjectMVC3.cs you're using the web activator method. – Brook Nov 18 '11 at 15:23
  • If you're using the web activator method, an easy way to get an instance of the kernel is to just use property injection `[Inject] public IKernel Kernel { get; set; }` on your MvcApplication – Brook Nov 18 '11 at 15:25
  • Yes, I'm using "WebActivator" method. I don't know the other one... I tried doing the property injection, but there's no "Cast" method available after "GetAll(type)". I don't know if this is the cause, but I ended up with a ArgumentNullException on that line. – tyron Nov 18 '11 at 15:52
  • Make sure you're including System.Linq... Actually, come to think of it, you don't even need the cast, just take it off. – Brook Nov 18 '11 at 15:54
  • Well, "Cast" wouldn't show up because of the missing System.Linq, indeed. But the NullException wasn't. Even with this [Inject] Kernel, Kernel is not receiving any value - it's always null. Without this, I can't make a relationship between FluentSecurity and Ninject... – tyron Nov 18 '11 at 16:32
  • Interesting, it looks like there is a bug regression in 2.2 regarding injecting to the Http Application. http://stackoverflow.com/questions/5512040/ninject-ing-a-dependency-in-global-asax/5514988#5514988 You might need to get a newer build than what is in nuget to make that work. – Brook Nov 18 '11 at 16:40
  • A different option would be to just change over to the "Inherit NinjectAppliction" method, which I'm pretty sure still works just fine, even if it's not as pretty as the web activator method. – Brook Nov 18 '11 at 16:46
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/5137/discussion-between-tyron-and-brook) – tyron Nov 18 '11 at 17:02
1

I had same problem like you had with Ninject. After hours of googling I downloaded the source code from github. I understood the code and debugged few methods to figured out how to resolve the services. All I have to do is provide a service locator to find the PolicyViolationException handlers.

Ninject equivalent seems to be like this.

configuration.ResolveServicesUsing(type => System.Web.Mvc.DependencyResolver.Current.GetServices(type));

I used Ninject MVC3 and I used below code to load the modules from my current MVC web project plus other assemblies.

private static void RegisterServices(IKernel kernel)
    {
        kernel.Load("*.dll");
        //kernel.Load(Assembly.GetExecutingAssembly());
    }

I configured PolicyViolationException handlers in my module:

public class MainWebNinjectModule : NinjectModule
{
    public override void Load()
    {
        // other bindings here
        Bind<IPolicyViolationHandler>().To<DenyAnonymousAccessPolicyViolationHandler>();
    }
}

Other required dependencies like ISecurityHandler, ISecurityContext etc are resolved by the internal IoC used in FluentSecurity.

Anil Vangari
  • 570
  • 7
  • 12