Windsor castle Injecting properties of constructed

2020-01-29 11:43发布

问题:

Some dependency injection containers enable you to inject configured services into an already constructed object.

Can this be achieved using Windsor, whilst taking account of any service dependencies there may be on the target object?

回答1:

No, it can't.



回答2:

This is an old question but Google led me here recently so thought I would share my solution lest it help someone looking for something like StructureMap's BuildUp method for Windsor.

I found that I could add this functionality myself relatively easily. Here is an example which just injects dependencies into an object where it finds a null Interface-typed property. You could extend the concept further of course to look for a particular attribute etc:

public static void InjectDependencies(this object obj, IWindsorContainer container)
{
    var type = obj.GetType();
    var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
    foreach (var property in properties)
    {
        if (property.PropertyType.IsInterface)
        {
            var propertyValue = property.GetValue(obj, null);
            if (propertyValue == null)
            {
                var resolvedDependency = container.Resolve(property.PropertyType);
                property.SetValue(obj, resolvedDependency, null);
            }
        }
    }
}

Here is a simple unit test for this method:

[TestFixture]
public class WindsorContainerExtensionsTests
{
    [Test]
    public void InjectDependencies_ShouldPopulateInterfacePropertyOnObject_GivenTheInterfaceIsRegisteredWithTheContainer()
    {
        var container = new WindsorContainer();
        container.Register(Component.For<IService>().ImplementedBy<ServiceImpl>());

        var objectWithDependencies = new SimpleClass();
        objectWithDependencies.InjectDependencies(container);

        Assert.That(objectWithDependencies.Dependency, Is.InstanceOf<ServiceImpl>());
    }

    public class SimpleClass
    {
        public IService Dependency { get; protected set; }
    }

    public interface IService
    {
    }

    public class ServiceImpl : IService
    {
    }
}


回答3:

As Krzysztof said, there is no official solution for this. You might want to try this workaround though.

Personally, I consider having to do this a code smell. If it's your code, why isn't it registered in the container? If it isn't your code, write a factory/adapter/etc for it.