ipjohnson / Grace

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

DefinesNamedScope: variable '' of type 'IExportLocatorScope' referenced from scope '', but is not defined #130

Closed canhazcodez closed 6 years ago

canhazcodez commented 6 years ago

I am trying to use the "DefinesNamedScope" functionality but I keep getting an exception when I try to locate.

DependencyInjectionContainer di = new DependencyInjectionContainer(c => c.Behaviors.ConstructorSelection = ConstructorSelectionMethod.Dynamic);
di.Configure(c =>
{
    c.Export<SimpleService>().As<ISimpleService>();
    c.Export<InjectsSimpleService>().As<IInjectsSimpleService>().ExternallyOwned().DefinesNamedScope("MyCustomScope");
});
var simple = di.Locate<ISimpleService>(); // works as expected
var olc = di.Locate<IInjectsSimpleService>(); // throws an invalidoperationexception "variable '' of type 'Grace.DependencyInjection.IExportLocatorScope' referenced from scope '', but it is not defined"

Am I using the DefinesNamedScope functionality wrong?

ipjohnson commented 6 years ago

@ElMaxxi I think you're using it correctly it sounds like it's a bug when combining dynamic constructor selection and the new defines named scope.

I'll take a look tonight or this weekend

canhazcodez commented 6 years ago

I got your dev branch to test and got another error when trying the following code:

public void SetupNestedInjectionWithScopes()
{
    _container.Bind<ISimpleService, SimpleService>(
        XBinding.WithScope(ScopeType.Named, "FirstScope"));
    _container.Bind<IOneLevelComplex, OneLevelComplex>(
        XBinding.WithScope(ScopeType.Named, "SecondScope"));
    _container.Bind<ITwoLevelComplex, TwoLevelComplex>(
        XBinding.WithScope(ScopeType.Named, "FirstScope")
        .StartsNamedScope("SecondScope"));
    _container.Bind<IThreeLevelComplex,  ThreeLevelComplex>(
        XBinding.StartsNamedScope("FirstScope"));
}

basically, it starts a scope "FirstScope" with the ThreeLevelComplex, then, with the TwoLevelComplex it checks if it is in that scope AND STARTS A SECOND SCOPE, "SecondScope" which is then checked by the OneLevelComplex, The SimpleService, which is injected inside the OneLevelComplex, checks to see if it is inside a "FirstScope".

Think -> Scope hierarchy.

The error that I am getting is complaining that it can't locate a scope with name SecondScope.

Any ideas?

p.s. this is not a huge problem, since we don't use scopes with different names, however, the test that I wrote works on ninject and doesn't work on grace.

ipjohnson commented 6 years ago

@ElMaxxi can you put the full example in a gist and I'll take a look this evening.

canhazcodez commented 6 years ago

@ipjohnson https://github.com/ElMaxxi/IocAdapter/blob/master/Tests/DirectTests.cs has a direct test with the code example, it is called GraceNestedScopes. However, the real test is SetupNestedInjectionWithScopes.

ipjohnson commented 6 years ago

@elmaxxi perfect thanks

ipjohnson commented 6 years ago

@ElMaxxi ok I took a look at your test and for Grace this configuration doesn't really make sense.

SingletonPerNamedScope lifestyle is intended to link the lifetime and disposal of the object to the scope with the name you are specifying.

DefinesNamedScope is asking the container to create a new scope and link the instance lifetime and disposal to the newly created scope.

Those two concepts are at odds with one another and ultimately I don't envision Grace trying to support this configuration.

canhazcodez commented 6 years ago

@ipjohnson your explanation makes perfect sense to me. As I mentioned, it is not a big problem for us, I was just wondering because this seems to work on ninject.

Thanks again for your, as usual, prompt answer. Cheers

ipjohnson commented 6 years ago

@ElMaxxi glad I could help