Ninject 2.0: Property Injection without attribute
Asked Answered
A

3

10

Is there a way to use Property Injection in Ninject 2 without using the [Inject] attribute? This creates a dependency to Ninject in the class that will be wired using it and I prefer to avoid having unneeded dependencies to my IoC container, that's why I end up using Constructor Injection more often.

I guess the same applies to Method Injection

Alida answered 12/7, 2010 at 18:53 Comment(0)
A
9

I followed Ruben's tip and posted a small blog post on how to achieve this, but here's the quick answer:

Create a custom attribute:

public class InjectHereAttribute : Attribute
{
}

The target class will now look like this:

public class Samurai
{
    [InjectHere]        
    public IWeapon Context { get; set; }
}

Now Ninject must be configured to use the custom attribute, this can be done by creating an implementation of IInjectionHeuristic that recognizes the custom attribute:

public class CustomInjectionHeuristic : NinjectComponent, IInjectionHeuristic, INinjectComponent, IDisposable
{
    public new bool ShouldInject(MemberInfo member)
    {
        return member.IsDefined(
          typeof(InjectHereAttribute),
          true);
    }
}

And finally add this behavior to the Ninject Kernel using the Components collection, it will run along the existing components, namely the default implementation of IInjectionHeuristic, which means either the default or the custom attribute can be used.

// Add custom inject heuristic
kernel.Components.Add<IInjectionHeuristic, CustomInjectionHeuristic>();
Alida answered 19/7, 2010 at 15:33 Comment(3)
The link no longer exists (thus illustrating why it's always better to copy/paste and give credit to the original author, rather than just linking to the original). Do you have an alternative resource to describe the original answer to this problem?Phasis
@BTownTKD you're right. I added the example to the answer and changed the broken link.Alida
This just make it so you don't have to depend on Ninject, but you still have to depend on a library everywhere, it just isn't ninject. If you have a dozen projects that don't depend on anything IoC related, you still have to add this dependency. Also, if you are registering an object you didn't create, from a NuGet package, you can't really add an attribute to it. I am not sure this is the right solution.Bulimia
C
4

You can pass in another [attribute] type to the Kernel upon creation which can be used instead of InjectAttribute, but you'll still have to reference something centrally OOTB.

There was a similar question very recently about doing PI without attributes - there's no OOTB (as in directly on the fluent configuration interface) to put in a custom scanner but the extensibility points (you add a component that implements a Ninject interface as you build your Kernel that dictates how that aspect is to be work if looking for a given attribute isnt't what you want) are in there to determine where to inject based on Convention over Configuration - there's nothing stopping you amending the scanning to be based on just an attribute name (so it doesnt necessarily have to live in a central location).

Note that, in general, constructor injection is good for lots of reasons anyway, including this one, and keeping you code container agnostic is important (even if you're currently happy with one!)

Currish answered 13/7, 2010 at 7:41 Comment(0)
C
3

I was able to accomplish this using a Heuristic class:

public sealed class MyInjectionHeuristic : NinjectComponent, IInjectionHeuristic
{
        private static readonly IList<Type> 
            _propertyInjectible = 
                new List<Type>
                {
             typeof(IMyService),
                };

                    /// <summary>
      /// Returns a value indicating whether the specified member should be injected.
      /// </summary>
      /// <param name="member">The member in question.</param>
      /// <returns><c>True</c> if the member should be injected; otherwise <c>false</c>.</returns>
      public bool ShouldInject(MemberInfo member)
      {
       var info = member as PropertyInfo;

       if( member == null || info == null )
        return false;

       if (info.CanWrite)
        return _propertyInjectible.Contains(info.PropertyType);

       if( this.Settings == null )
        return false;

       var propList = member.GetCustomAttributes(this.Settings.InjectAttribute, true);

       return propList.Length > 0;
      }
}

When creating your kernel:

var heuristics = _kernel.Components.Get<ISelector>().InjectionHeuristics;
   heuristics.Add(new MyInjectionHeuristic());

Simple add additional types to the IList when you want to inject other types via properties.

Collusive answered 13/8, 2010 at 22:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.