ipjohnson / Grace

Grace is a feature rich dependency injection container library
MIT License
336 stars 33 forks source link

Property injection not populated when target instance is also in container #275

Closed dtkujawski closed 3 years ago

dtkujawski commented 3 years ago

This is a bit tricky to explain with words, but I think the code makes it easier to see. For reference, take the following interfaces and classes for this example (as simplified as I could boil everything down):

        public interface IChild { }
        public class Child : IChild { }

        public interface IParent { }
        public class Parent : IParent
        {
            [Import] public IChild Child { get; set; }
        }

In a scenario where I register Child/IChild in the container and then get an instance of Parent directly, everything is wired up just fine:

        var container = new DependencyInjectionContainer();
        container.Configure(c => c.Export<Child>().As<IChild>());

        var parent = container.Locate<Parent>();
        Assert.NotNull(parent.Child);                  //PASSES

But, if I were to also put Parent/IParent in the container and then call Locate the DI would not resolve and the Child property would be null:

        var container = new DependencyInjectionContainer();
        container.Configure(c => c.Export<Child>().As<IChild>());
        container.Configure(c => c.Export<Parent>().As<IParent>());

        var parent = container.Locate<IParent>();
        Assert.NotNull((parent as Parent).Child);      //FAILS

Even in the case where I register the class directly (not the IParent interface, but the Parent type) it still fails:

        var container = new DependencyInjectionContainer();
        container.Configure(c => c.Export<Child>().As<IChild>());
        container.Configure(c => c.Export<Parent>());

        var parent = container.Locate<Parent>();
        Assert.NotNull(parent.Child);                 //FAILS

Is this expected behavior?

NOTE: If I add a constructor-based DI to the Parent class, everything works fine.

ipjohnson commented 3 years ago

Hi @dtkujawski, while it seems kind of odd it's actually expected behavior but there are work arounds. Let me explain why it doesn't work first.

You can add .ProcessAttributes() to the end of your fluent call if it's a one off. Or you can add an IActivationStrategyInspector and do it automatically. I've added a test case here as an example of how to do it.

dtkujawski commented 3 years ago

@ipjohnson, that worked perfectly. Thank you very much!