Ninject Binding Conditionally When Injecting To A Generic Interface

52 Views Asked by At

I have the following code structure which I want to compose with Ninject:

ICommandHandler<FindAssetById, Asset> handler =
    new SecurityCommandHandlerDecorator<FindAssetById, Asset>(
        new SecurityValidatorComposite<FindAssetById>(
            // This list contains both non-generic as generic implementations
            new ISecurityValidator<FindAssetById>[]
            {
                // Contains type constraint 'where T : IRequireAccessToAsset'
                new RequireAccessToAssetSecurityValidator<FindAssetById>(...)
            }),
        new FindAssetByIdHandler(...));       

I have this setup in my Ninject:

//Bind Composite To Handler
_kernel.Bind(typeof(ISecurityValidator<>))
 .To(typeof(SecurityValidatorComposite<>))
 .WhenInjectedInto(typeof(SecurityCommandHandlerDecorator<,>));

//Bind Interface To Concrete
_kernel.Bind(typeof(ISecurityValidator<>))
  .To(typeof(RequireAccessToAssetSecurityValidator<>))
  .WhenInjectedInto(typeof(SecurityValidatorComposite<>));

_kernel.Bind(typeof(ISecurityValidator<>))
  .To(typeof(RequireAccessToSecureAssetSecurityValidator<>))
  .WhenInjectedInto(typeof(SecurityValidatorComposite<>));

I want to be able to conditionally bind the concrete validators if the calling parent implements the corresponding interface.

For instance a class like this:

public class FindAssetById: IRequireAccessToAsset{

}

Should get the RequireAccessToAssetSecurityValidator but not the RequireAccessToSecureAssetSecurityValidator. With Ninject the current way it is setup it obviously gets both. But with Ninject you can't call WhenInjectedInto and a conditional When statement. With how difficult this has been I'm assuming at this point I am way off base and how to implement and any suggestions to fix this would be very helpful.

In Simple Injector the equivalent would be something like this:

container.Register(
    typeof(ISecurityValidator<>),
    typeof(SecurityValidatorComposite<>),
    Lifestyle.Singleton);

container.Collection.Register(typeof(ISecurityValidator<>), assemblies);

container.Collection.Append(typeof(ISecurityValidator<>), 
    typeof(RequireAccessToAssetSecurityValidator<>));

And somehow it knows to apply the right one or the example provided is incomplete. I'd like to replicate something like this with Ninject as I think the solution from here is fairly clean and where I got most of my code from https://github.com/dotnetjunkie/solidservices/issues/4. This is my first foray into really trying to understand DI and how I can apply the decorator pattern with it so any help would be greatly appreciated.

0

There are 0 best solutions below