You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
How do I get the name / type of the class that's trying to resolve a dependency, let's say via ctor injection? I tried to resolve IInjectionContext and StaticInjectionContext in ExportFactory but neither of the objects contained any useful information.
Hmmm you should be able to get it from the StaticInjectionContext . I'm guessing the static context wasn't passed through correctly for the ExportFactory.
I'll see if I can take a look tonight or tomorrow. I don't think it should be hard to address
Thanks! There's an enum value there indicating how the dependency call was made, but it seems to always be set to Root, maybe that's related (should be Constructor Injection or something like that).
That's what I suspected when the factory is being created it's being rooted and it's not carrying any context information over. That's incorrect and shouldn't be too hard to address.
The normal Singleton lifestyle "roots" everything so that no context is carried over as well as no dependencies can be carried. This is to insure that an instance is created the same no matter which parent is constructed first (otherwise you can end up with race conditions where it constructs differently between runs).
I can make some changes to the deferred singleton lifestyle to make this possible but I can't do it today.
Ok I've implemented a change to make this possible. Normally a singleton is "rooted" this is to prevent a dependency from being constructed differently based on a race condition. This change makes it so which ever path resolves the dependency first dictates how the dependency is constructed.
@ipjohnson Thanks for pointing me in the right direction. I tried out your code but it made no difference. In the StaticInjectionContext, the TargetInfo.InjectionDependencyType is still of type Root and I'm not able to determine the caller of the dependency resolution.
Perhaps I'm misunderstanding some concepts here. The dependency to be resolved is a generic, e.g. IDependency<T>:
IDependency<Type1> resolves as Dependency1 IDependency<Type2> resolves as Dependency2
Grace should cache (store) IDependency<Type1> as a singleton with the implementation of Dependency1 and IDependency<Type2> as a singleton with the implementation of Dependency2.
I think I understand what you're talking about. I don't really have a life style that's going to do that but I think it can be achieved with a little bit of code.
I'll try and find some time today or tomorrow morning to write up an example of what it would look like.
Ok I added a test where you inject a transient with a non generic interface, where the implementation is a generic that is closed by the injecting type and singleton. Let me know if this is close to what you were thinking.
The test looks good in my eyes! Will I be able to read which class was calling on the dependency as the Lifestyle is Transient?
Also, does it have to specifically be a generic implementation? IMHO IDependency could link to any class based on some custom condition or dependent on which class is trying to resolve the dependency.
Correct, it doesn't need to be generic nor do you need the concurrent dict. It was just an interesting proof of concept where you close the generic with the parent type.
Hey @ipjohnson, I've had some time to take a closer look at this during the holidays but am yet to get it to work. The result I'm getting is the one I mention in #264 (comment) and I've tried using the custom Deferred lifestyle but it doesn't seem to have any effect.
Can it be of importance that I'm requesting this dependency through a Controller method via the [FromServices] attribute?
Activity
ipjohnson commentedon Jun 3, 2020
Hmmm you should be able to get it from the
StaticInjectionContext. I'm guessing the static context wasn't passed through correctly for theExportFactory.I'll see if I can take a look tonight or tomorrow. I don't think it should be hard to address
silkfire commentedon Jun 3, 2020
Thanks! There's an enum value there indicating how the dependency call was made, but it seems to always be set to
Root, maybe that's related (should be Constructor Injection or something like that).ipjohnson commentedon Jun 3, 2020
That's what I suspected when the factory is being created it's being rooted and it's not carrying any context information over. That's incorrect and shouldn't be too hard to address.
ipjohnson commentedon Jun 6, 2020
So it's not as simple as I originally thought because for simple cases it's working as seen in the test
What does the registration look like does it have a lifestyle on it? If so that can cause it to be rooted.
silkfire commentedon Jun 7, 2020
That's correct, I'm setting a Singleton lifestyle on the registered dependency.
ipjohnson commentedon Jun 9, 2020
could you put together a quick sample, I wasn't able to reproduce this but I'm not sure I have it setup the same way you do.
silkfire commentedon Jun 9, 2020
You're correct, Ian, it seems to work if I don't specify the Singleton lifestyle. The test below should be sufficient to reproduce this scenario:
ipjohnson commentedon Jun 10, 2020
The normal Singleton lifestyle "roots" everything so that no context is carried over as well as no dependencies can be carried. This is to insure that an instance is created the same no matter which parent is constructed first (otherwise you can end up with race conditions where it constructs differently between runs).
I can make some changes to the deferred singleton lifestyle to make this possible but I can't do it today.
silkfire commentedon Jun 10, 2020
Don't feel stressed, I'm okay with waiting awhile for a proper solution. Great that you were able to pinpoint the cause of this :)
silkfire commentedon Jul 6, 2020
Any update on this one, Ian? ☝🏻
ipjohnson commentedon Jul 7, 2020
Sorry I've been pretty busy as of late. I have some time this weekend to address a couple Grace items and I'll do a release with this in.
adding option to do non rooted singleton issue #264
ipjohnson commentedon Jul 12, 2020
Ok I've implemented a change to make this possible. Normally a singleton is "rooted" this is to prevent a dependency from being constructed differently based on a race condition. This change makes it so which ever path resolves the dependency first dictates how the dependency is constructed.
Are you able to test it in the nightly?
ipjohnson commentedon Jul 23, 2020
I've released this to nuget. Marking as completed.
3 remaining items
silkfire commentedon Jul 27, 2020
@ipjohnson Thanks for pointing me in the right direction. I tried out your code but it made no difference. In the
StaticInjectionContext, theTargetInfo.InjectionDependencyTypeis still of typeRootand I'm not able to determine the caller of the dependency resolution.Perhaps I'm misunderstanding some concepts here. The dependency to be resolved is a generic, e.g.
IDependency<T>:IDependency<Type1>resolves asDependency1IDependency<Type2>resolves asDependency2Grace should cache (store)
IDependency<Type1>as a singleton with the implementation ofDependency1andIDependency<Type2>as a singleton with the implementation ofDependency2.silkfire commentedon Jul 28, 2020
I think I've realized that I might've been wrong all along.
IDependency.Dependency<T>.Dependency<T>to be resolved.Dependency<T>isn't already registered by Grace, create the instance and then store it as a singleton.So the Transient
IDependencywould act as a proxy to the singleton implementation of typeDependency<T>.ipjohnson commentedon Jul 28, 2020
I think I understand what you're talking about. I don't really have a life style that's going to do that but I think it can be achieved with a little bit of code.
I'll try and find some time today or tomorrow morning to write up an example of what it would look like.
silkfire commentedon Jul 28, 2020
Thank you. Apologies for my confusing train of thought 😅
adding example test for issue #264
ipjohnson commentedon Jul 30, 2020
Ok I added a test where you inject a transient with a non generic interface, where the implementation is a generic that is closed by the injecting type and singleton. Let me know if this is close to what you were thinking.
silkfire commentedon Jul 31, 2020
The test looks good in my eyes! Will I be able to read which class was calling on the dependency as the Lifestyle is Transient?
Also, does it have to specifically be a generic implementation? IMHO
IDependencycould link to any class based on some custom condition or dependent on which class is trying to resolve the dependency.ipjohnson commentedon Jul 31, 2020
Correct, it doesn't need to be generic nor do you need the concurrent dict. It was just an interesting proof of concept where you close the generic with the parent type.
silkfire commentedon Aug 3, 2020
Is this planned for an upcoming release?
ipjohnson commentedon Aug 4, 2020
The latest code line is released as a beta on nuget. I'll probably look to do a non beta release in the next week or two.
silkfire commentedon Dec 29, 2020
Hey @ipjohnson, I've had some time to take a closer look at this during the holidays but am yet to get it to work. The result I'm getting is the one I mention in #264 (comment) and I've tried using the custom Deferred lifestyle but it doesn't seem to have any effect.
Can it be of importance that I'm requesting this dependency through a Controller method via the
[FromServices]attribute?ipjohnson commentedon Dec 30, 2020
Hi @silkfire
you’re correct the [FromServices] attribute is handled through the MVC framework and is a new request to the container.
azuraji commentedon Dec 30, 2020
Hmmm, so that's why it hasn't been working all along. Is there a way this can be solved?
ipjohnson commentedon Dec 30, 2020
Not without completely changing the way the [FromService] attribute works.
silkfire commentedon Dec 30, 2020
@ipjohnson Shame, I find it quite useful. Would it be possible to hack up a custom one, and let's call it
[FromGrace]? 😂