NonInjectable Service?

If you were reading my previous posts you will notice that I am injecting entities in my IoC. This way the container can inject services in your entities. The other reason to inject entities in your container is when you container integrates very well with a proxy generator (as you can read in my examples of AOP).

The problem is entities are not injectable, the container should inject services in entities but not entities in services nor entities in entities.

So, this is my code snippet for Windsor Container.
The facility:

public class NonInjectableFacility : AbstractFacility
{
    public const string NonInjectablePropertyKey = "noninjectable";

    private readonly ArrayList _nonInjectables = new ArrayList();

    private void Kernel_ComponentModelCreated(ComponentModel model)
    {
        if (model.ExtendedProperties.Contains(ExtendWithPropertyKey))
        {
            _nonInjectables.Add(model.Service);
            foreach (ComponentModel componentModel in Kernel.GraphNodes.OfType<ComponentModel>())
                RemoveNonInjectables(componentModel);
        }
        RemoveNonInjectables(model);
    }

    private void RemoveNonInjectables(ComponentModel model)
    {
        List<PropertySet> propertiesToRemove = model.Properties
            .Where(p => _nonInjectables.Contains(p.Property.PropertyType))
            .ToList();

        foreach (PropertySet propToRemove in propertiesToRemove)
            model.Properties.Remove(propToRemove);
    }

    protected override void Init()
    {
        Kernel.ComponentModelCreated += Kernel_ComponentModelCreated;
    }
}

A registration extension:

public static class FluentRegister
{
    public static ComponentRegistration<T> NonInjectable<T>(
this ComponentRegistration<T> registration) { registration.ExtendedProperties(
Property.ForKey(NonInjectableFacility.NonInjectablePropertyKey).Eq(true)); return registration; } }

And the test:

[Test]
public void should_work()
{
    var c = new WindsorContainer();
    c.AddFacility<NonInjectableFacility>();

    c.Register(Component.For<IInjectableService>()
                   .ImplementedBy<InjectableService>());

    c.Register(Component.For<Service>());

    c.Register(Component.For<ITopMostService>()
                   .ImplementedBy<TopMost>().NonInjectable());

    c.Resolve<Service>().TopMostService.Should().Be.Null();
}

Note: Windsor has an attribute called [DoNotWire].

I took some ideas from Mauricio Scheffer’s answer in this thread and also I’ve stolen others ideas from this post of Tuna Toksoz.


blog comments powered by Disqus
  • Categories

  • Archives