Custom Ninger-based bindings + decorators

We use Ninjects-based convention bindings to automatically associate a set of commands and queries with their handlers. So far, we have one decorator working using the following.

Bind all without an attribute:

Kernel.Bind(x => x.FromThisAssembly() .SelectAllClasses() .InheritedFrom(typeof(ICommandHandler<>)) .WithoutAttribute<DoCheckAttribute>() .BindAllInterfaces()); 

Bind all attribute:

  Kernel.Bind(x => x.FromThisAssembly() .SelectAllClasses() .InheritedFrom(typeof(ICommandHandler<>)) .WithAttribute<DoCheckAttribute>() .BindAllInterfaces() .Configure(c => c.WhenInjectedInto(typeof(DoCheckDecorator<>)))); 

We tried the following to add another decorator, however this fails.

Bind all without an attribute:

  Kernel.Bind(x => x.FromThisAssembly() .SelectAllClasses() .InheritedFrom(typeof(ICommandHandler<>)) .WithoutAttribute<DoCheckAttribute>() .WithoutAttribute<DoOtherCheckAttribute>() .BindAllInterfaces()); 

Bind all attribute:

  Kernel.Bind(x => x.FromThisAssembly() .SelectAllClasses() .InheritedFrom(typeof(ICommandHandler<>)) .WithAttribute<DoCheckAttribute>() .WithoutAttribute<DoOtherCheckAttribute>() .BindAllInterfaces() .Configure(c => c.WhenInjectedInto(typeof(DoCheckDecorator<>)))); Kernel.Bind(x => x.FromThisAssembly() .SelectAllClasses() .InheritedFrom(typeof(ICommandHandler<>)) .WithoutAttribute<DoCheckAttribute>() .WithAttribute<DoOtherCheckAttribute>() .BindAllInterfaces() .Configure(c => c.WhenInjectedInto(typeof(DoOtherCheckDecorator<>)))); 

Is it possible to achieve this this way using Ninject? Do I need to return to the definition of each binding manually?.?

  Bind<X>.To<Y>.WhenInjectedInto(?) 

Ideally, we would use syntax, for example:

  Bind<X>.To<Y>.WithDecorator<Z>.When(a => a.HasAttribute<DoCheckAttribute>) 
+4
source share
1 answer

So, it seems that Ninject already has an extension that can solve this problem. Using the interceptor extension, you can write the attribute as:

  [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] public sealed class DoCheckAttribute : InterceptAttribute { public override IInterceptor CreateInterceptor(IProxyRequest request) { return request.Context.Kernel.Get<DoCheckInterceptor>(); } } 

The actual interception is then written as:

  public class DoCheckInterceptor : IInterceptor { public void Intercept(IInvocation invocation) { //Do Work invocation.Proceed(); } } 

This means that the bindings are as simple as:

  Kernel.Bind(x => x.FromThisAssembly() .SelectAllClasses() .InheritedFrom(typeof(ICommandHandler<>)) .BindAllInterfaces()); 

New attributes can now be easily added without any binding changes. Multiple attributes may also have the order in which they are executed, for example:

  [DoCheck(Order = 0), DoOtherCheck(Order = 1)] public class TestClass { } 
+3
source

Source: https://habr.com/ru/post/1483526/


All Articles