Comments (33)
The good news is, it passes all tests in v6.
Unity v5 fails few of these.
If you want to contribute a fix, the key is to use "Owner" property on the ImplicitRegistration to initialize a BuilderContext.Container if lifetime manager is ContainerControlledLifetimeManager.
from container.
Is it important for you to have dependencies Disposable? If they are not, you could just hold references to these from the singleton.
This is interesting situation though and presents certain challenges. Could you create a Unity Test I could play around with?
from container.
I will provide a test case illustrating this tomorrow. It will be easier to explain the problem that way, you are right. Thanks again!
Best regards
Jarik
from container.
Hi @ENikS
I made some unit tests to illustrate what exactly I mean by this topic.
I tried to make an extension to redirect the resolution for singletons, but it didn't work, I am afraid, I don't have enough info about how the internals of Unity work, here is what I did:
public sealed class SignletonBuilderStrategy : BuilderStrategy
{
private readonly SignletonBuildExtension _extension;
public SignletonBuilderStrategy(SignletonBuildExtension extension)
{
_extension = extension;
}
public override void PreBuildUp(ref BuilderContext context)
{
// this is just to illustrate, will use attributes to detect singletons here
if (context.Type.Name.Contains("GlobalSingleton") && context.Container.Parent != null)
{
context.Existing = extension.ResolveInRootScope(context.Type);
context.BuildComplete = true
}
base.PreBuildUp(ref context);
}
}
I hope, you can point in a direction or otherwise advise about a solution/workaround. Thanks!
Regards
/Jarik
from container.
Did you see this Singleton Lifeteime?
from container.
Yes, I have . As pr your request I made few unit tests, and the singleton type in the test target is registered as InstanceLifetime.Singleton:
Or maybe you mean something different?
from container.
Hi @ENikS , have you had any time to look at the test cases? I see that my branch is now failing, but I guess that is unrelated.
/Jarik
from container.
from container.
Ok, thanks! 👍
from container.
After looking into this long and hard I can conclude that this is a correct behavior. Every resolution runs in the context of the executing container. This is by design from the dawn of time and could not be changed.
from container.
Ok, I see, thank you for you time. But do you think there is a workaround to bypass/reconfigure this behavior? I am not talking about changing the default flow, but perhaps som extension mechanism to override it?
from container.
from container.
I can do that if I am resolving a singleton type directly, then it is possible to check. But if the singleton is somewhere down the chain of the dependencies, then it is out of my control. This is why I was trying to intercept a singleton in BuilderStrategy in my example above and redirect it to be resolved in the root, but this approach didn't work. Do you think it is possible at all (without modifying the unity code)?
from container.
What stops you from preemptively creating it right after you registered the singleton?
You could create a type factory, same as Unity's Func<>
or Lazy<>
. Each container has a pointer _root...
from container.
Hi @ENikS ,
I tried what you suggested and unfortunately, I was not able to find a satisfactory solution by re-wrapping the singletons into Lazy/Factory constructs, it is complicated and difficult to implement in the code base.
However, I managed to build this logic into Resolve-flows in the UnityContainer (only for 5.10.3) , and the proposed fix actually resolved the problems. Would you kindly review the pull request and let me know if this is a good solution or what should be re-written to achieve same behavior?
Thanks!
Best regards
Jarik
from container.
@jarikp
Your change significantly alters Unity's behavior. I am still not convinced it is broken to begin with.
Limiting resolution to the level of registration changes one of the main resolve specs and I don't think it is justified.
Now, if it is done for the singleton, it would have to apply to Container Controlled lifetime as well? Same issue...
from container.
Yes, I completely agree that this is potentially breaking change with serious impact.
The problem is that I don know how it should be implemented otherwise?.. The real need here is to create some kind of "super" singleton (or "global" singleton ?) which is never going to be corrupted if the container where it was resolved first time is disposed later, implying that the singleton itself and all its dependencies, sub-dependencies etc including factories (this is important!) have infinite lifetime or at least until the root is torn down.
So maybe to prevent any issues like breaking existing lifetime of Unity, it would be better idea to define a new manager option in Unity.TypeLifetime, like RootedSingleton or GlobalSingleton etc? And use that to enable the desired behavior? This will at least be more explicit for developers and the existing behavior will remain unchanged.
from container.
Why not register all relevant types in the root, resolve the singleton, and only then create child containers?
from container.
Well, some constraints preventing doing this workaround could be due to architecture limitations, app design, performance reasons (resolving can be expensive and only wanted on demand) or the cost of refactoring.
Here is an example of how this problem is translated into the real-life usage of Unity:
Imagine you have an app, and when you start the app, you can open different child windows for from app. The main window of the app will be representing the root container (if you close the main window, the app is terminated). Each new window will be created as a child container. With this design each window will have its own scope, where it can host its own "local" singletons (states).
However, some of the services in the app are globally shared, and only one instance of each is allowed to exist – let's call them "global" singletons. Due to start-up performance, memory consumption and sometimes licensing limitations they are not resolved when the app is launched, but only when needed during the lifetime of the running process. Anyway, there is a window, which will resolve such a global service when opened first time. Then when you open a different window using same service, it will get the very same instance of the service, etc….
The problem now is that if you close the first window, before you open the second one, the corresponding child container of that window is disposed. Which means all dependencies of the singleton service are potentially broken (since they were all resolved in that container and never promoted to the root). And when you open the second window, it will indeed get the same singleton service, but everything in its dependency chain will be corrupted, as the owning container was disposed, when you closed the first window.
So due to the application design it is not possible to pre-resolve those things during the startup. It needs to be managed by the unity container, when (and IF) a global singleton is resolved for the first time.
The registration of types is done in the root container already, this is not the problem .
from container.
Just because one application has certain design requirements it does not warrant change to basic container behavior. I already offered at least couple of different solutions to the problem. The behavior you describe could be easily achieved by implementing any of these.
from container.
Hi @ENikS
First, thank you for the time you are spending on this, it is really appreciated. I do understand, how this problem might look from your side, and it is hard for me to run this campaign :)
Your proposed solutions are valid in general, but they are very hard to implement in my case. In the system I am working on (consisting of multiple applications) there are almost 10000 types which are all registered in the containers, with very complicated dependency chains and different lifetime types. And the UnityContainer has been in its IoC core since the beginning.
This issue is preventing the upgrade to version 5.x of the container, it looks like version 4.0.1 which is used now, does not show this problem at runtime as often as version 5 - for whatever reason. But I suspect that version 5 is much faster with resolve/teardown, which unveils the problem with singletons in closed child containers.
I also think that the lifetime management as this is a responsibility of the IoC container / framework, not the application itself. Therefore, I keep looking for a solution in the Unity Container, instead of doing the manual bookkeeping in the application.
The good thing is that the UnityContainer is already able to help me with all of this! It can be done without changing a single line of the application code, this is what I showed you in the pull request. And to make it clear, it does not have to be a change to the fundamental behavior of the container. I am suggesting this as an optional mode of operation, that should be enabled explicitly by a special lifetime type or maybe some configuration flag.
I am offering help to implement this, but I guess it will not make sense if you totally against any possible change in that direction…
Best regards
Jarik
from container.
from container.
After thinking about it a bit more I admit, you are making a valid point. Some lifetimes do require limiting scope to the container where they are registered.
I will try to implement it in next release of Unity.
from container.
Hi @ENikS
This is really great news! 👍
I know that you are busy working on v.6, and I'd be happy to help implementing it in v.5 branch. I think UnityContainer is really interesting project and would like to contribute to it.
If you could share your thoughts about a solution design, I can give you a hand to with writing code and tests
Best regards,
Jarik.
from container.
from container.
Hi @ENikS,
Have you had a chance to review the spec tests, are they in the format you would expect?
Best regards,
Jarik
from container.
I've incorporated them into spec test suilte
from container.
Hi again,
Thanks for closing this. I am not sure, if it that you have changed the behavior of unity so it now works as wanted in the cases above?
Also, I see that my pull request with the test cases is still pending, and they are not in the source code.
The reason I am asking is because you wrote earlier:
"I will add necessary changes to Abstractions and will let you know how it could be fixed in v5. I will be out of town for few days, so perhaps next week… Meanwhile if you could come up with all the necessary tests it would be great. I have relevant set of tests you could add to here... "
So I don't follow your decision to close this and not using the things you asked me to help you with?..
Best regards
Jarik
from container.
PR was merged but I moved and renamed some of the tests
from container.
Hi Eugene,
I am talking about this one:
unitycontainer/specification-tests#2
It is mentioned in this thread, just below your message 24 days ago.
But maybe there is some kind of misunderstanding? 🤔
Best regards
Jarik
from container.
I've merged it too. Missed it somehow.
from container.
@ENikS, I see that all tests are green now on v5. In the code it looks like you have fixed the remaining bits of this issue, and there is no more expected work left? Sorry if this is obvious for you, but I could not find any relevant info or release notes about this.
from container.
from container.
Related Issues (20)
- Possible regression in nested containers and ContainerControlled lifetime HOT 4
- Upgrading from 4.0.1 to 5.11.8. Question about TearDown and IBuilderPolicy HOT 3
- UnityContainerExtensions.Resolve(this IUnityContainer container, Type t, string name, params ResolverOverride[] overrides) seems to be missing HOT 1
- BuildUp with InjectionMethod run-time configuration and Diagnostic() throws "Injected method could not be matched with any public methods"
- Empty Version Zip And Tar.gz files (unity-5.8.13.576) HOT 1
- Unity.nuspec does not explicitly list DLL dependencies, which cause runtime issues
- Unable to resolve from ChildContainer when using singleton HOT 1
- Is it really necessary for a UnityContaner to hold the list of the ChildContainers created by it? HOT 16
- Is there a possibility to remove Extensions that have been added with container.AddExtension(....)? HOT 1
- Enabling diagnostic breaks functionality HOT 1
- RegisterInstance() throws incorrect exception
- ResolvedParameter() and OptionalParameter() ignore name of the dependency
- Is CommonServiceLocation replaced with CommonServiceLocator HOT 1
- Intermittent Failure During Resolve Process HOT 1
- VerificationException in TransientLifetimeManager on Azure DevOps HOT 1
- Override MethodProcessor HOT 6
- RegisterType throws InvalidOperationException when no constructor could be matched with injected member
- Invalid ("dead") license URL for NuGet package 'Unity'
- Stackoverflow even with `Diagnostic` extension enabled HOT 8
- ResolverOverride Legacy Extension not working in Unity > 5.11.6 when using .NET Framework 4.8, or .NET6
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from container.