I have developed a silverlight prism project to replicate a memory leak. Just wondering about the lifecycle of a prism module.
If inside a module I register a view does the view get destroyed when the module is no longer in use?
Also does each module share the same dependency container (e.g. unity) or does each module have a separate one?
I have a more in depth question here,
https://stackoverflow.com/questions/4652364/memory-usage-is-suspect-when-loading-prism-modules
I am trying to understand some discrepancies with memory usage when opening and closing prism modules.
1) The point in time the view gets destroyed depends on the way you have registered the view to the container. If you didn't change the object lifecycle during registration, it will be destroyed when the GC finds it without having any object referencing it. If you explicitly specified a lifetime manager during the registration the view gets destroyed depending on the particular lifetime the manager manages. An exmaple: When you are using a Unity container and you registered the view with a ContainerControlledLifetimeManager the view gets destroyed when the container gets destroyed.
2) All modules share one container as long as you don't make a child container for each module on your own.
Related
I am having some issues with context lifetime on my .NetCore 6 win forms application. In summary, I have a button that when clicked calls a repository which then retrieves a record from my DB and displays one value from that record in a text field. This works ok until that value changes in the database. Further clicks of the button continue to display the old value.
This is how I register my context in the winforms app
services.AddDbContext<MyContext>(b => b.UseSqlServer(connectionString));
I then register my services like this:
services.AddScoped<IMyRepo, MyRepo>();
I guess this is an issue where the form is long running and never disposes the context, hence why the result is always the same until the form is closed and reopened with a fresh context.
I am using this in my repo to force a new result each time, however is seems like a bit of a mission to do this for every request to the DB I make...
_entities.Entry(log).Reload();
Is there a cleaner way I can do this without having to do the reload?
Honestly, I wouldn't use the MS IoC AddDbContext for WinForms/WPF. There probably is a way to have it play nice with some form of lifetime scope, but I'm honestly not aware of one. I don't use it for web projects either, simply because it scopes the DbContext to the request and I like to have a bit more control over the lifetime of the DbContext in some situations. (Dealing with poisoned contexts for instance)
For web and WPF I've used a Unit of Work pattern called the DbContextScope to manage the DbContext and relationship with the Repositories. The idea being that the consumers use an injected DBContextScopeFactory to create a DbContextScope (wrapping one or more DbContext instances) and the Repositories accept an injected DbContexScopeLocator to gain access to a requested DbContextScope.
The original EF6 implementation was by Medhi El Gueddari (https://github.com/mehdime/DbContextScope || https://www.nuget.org/packages/Mehdime.Entity)
For EF Core 6: (https://www.nuget.org/packages/Zejji.DbContextScope.EFCore6)
Alternatively if the scope of a DbContext can be contained within the repository calls themselves (tracked entities don't need to be passed outside of the repository) then you could also just use an injected DbContextFactory class to provide DbContext instances on demand. The advantage of a UoW pattern like above is that you have control over the scope the DbContext instance(s) live so multiple operations can be committed together or rolled back. The DbContext instance is available between multiple repositories if needed.
I'm using DotnetCore, WPF and Prism 7 to make a desktop application. I have one service called DbConnectionService that doesn't seem to be created. This service is not injected into any component that is reachable through the View tree(?). Instead, it listens to the IEventAggregator and communicates with the rest of the app through that.
I'm finding that I'm not able to get it to 1. be created, and 2. if it is created it doesn't stick around (GC I assume).
Below is the code I have "shotgunning" anything that will create the DbConnectionService. All to no avail.
containerRegistry.RegisterInstance(typeof(DbConnectionService), "DbConnectionService");
containerRegistry.Register<IDbConnectionService, DbConnectionService>();
containerRegistry.RegisterSingleton(typeof(DbConnectionService));
containerRegistry.GetContainer().RegisterSingleton<DbConnectionService>();
Any help on getting this service to be created and stick around is greatly appreciated.
This service is not injected into any component
That's why it's not created. Either you inject it and rely on the container's magic to create it, or you create it yourself.
You can use the container to keep the object alive (i.e. not garbage collected) through RegisterInstance:
containerRegistry.RegisterInstance( containerRegistry.GetContainer().Resolve<DbConnectionService>() );
Note that Resolve isn't on IContainerRegistry to prevent you from doing this, because you don't want to mix registering and resolving. If you have to, make 110% sure that all dependencies of DbConnectionService are registered beforehand.
I need to display views in a Module.The Module Registers it's view using in Initialize method.
User will select module name from drop down list. First time it works using IModuleManager.LoadModule(string ModuleName). If I want to re-display the same module again(in the same region after clearing the previously displayed module) IModuleManager.LoadModule is not going to work. I dont know the views and regions contained in that Module. I know just ModuleName and I need to display it's view.
How can I do that?
Your questions is very confusing. Can you provide more information? The IRegionManager is the component to register Views to your predefined Regions. The ModuleManager is only responsible to load an assembly if I got that right.
I don't think you can Load a Module multiple times, because the second time it is loaded already. The logic for displaying views should be regulated via Services within your Modul so inside your Module should be a Method that uses the IRegionManager to register a specific View to a Region.
I don't know whether you use Unity or MEF ( or another IOC ) but you can obtain the IRegionManager within your Module via the Container.
Maybe you should watch this Tutorial series Prism Tutorial Series. It seems to me you are missing some basic principles
I want to build a WPF/Prism application where each top level window is in its own UI thread. That is fairly straight forward to do. I am using Unity as my DI container and would like to create a hierarchy of containers. In the simplest case, the root container will be at the application level and each window will have a child container. This is desirable as each window can have its own shared objects scoped by the child container.
I would like each window to have their own region manager from Prism so that I don't have any cross threading issues as each Window will have its own UI thread. I see that the Region and RegionManager use the ServiceLocator.Current singleton. This is an issue because I would like the RegionManager to use the container it is scoped to which is not possible with a static singleton. Have any of you run into this issue and how would you work around it?
Thanks!
You can have your Bootstrapper as child container and register your types there. And have your ServiceLocater in the application level which will call your Bootstrappers.
more info about; http://msdn.microsoft.com/en-us/library/ff649077.aspx
I actually needed to do the same thing, and I figured out the following solution:
Before navigating to the "child" region, do the following:
var childRegion = _childRegionManager.Regions["ChildRegion"];
_childRegion.NavigationService = _childContainer.GetExportedValue<IRegionNavigationService>();
_childRegion.NavigationService.Region = _childRegion;
This sets the correct navigation service on the child region.
Of course, childContainer should have an IRegionNavigationService in its own catalog, so that it will compose it properly.
I have come across a bit of a problem while using Unity and WPF. The scenario is I have a WPF application which follows the MVVM design pattern. A have a module called ViewKDI. Within this module I have a service called ViewKDIService, the ViewKDIService service utilises another service called UserService.
Every time I load the module ViewKDI I want Unity to return me a new instance of both the ViewKDIService and the UserService.
I have put the below in the shell bootstrapper:
Container.RegisterType<IUserService, UserService>();
In the ViewKDI module I have put the following:
Container.RegisterType<IViewKDIService, ViewKDIService>();
Each time the ViewKDI module loads the ViewKDIService constructor is called. However the UserService constructor is only called the first time, this means that I am not getting a new instance of UserService.
I require unity to give me a new instance of UserService too so that I can manage this session separately from the rest of the application.
Any ideas?
Thanks
Faisal
Unity's default behaviour is to create a new instance of each object each time one is requested, so you shouldn't be seeing this behaviour.
From what I can gather from the source code and MSDN documentation (this is a good read), you can specify a "lifetime manager" object when you register a type to tell Unity how the type should be constructed and cached. Using the TransientLifetimeManager (which essentially does no caching) will cause Unity to re-create the class each time. So try this:
Container.RegisterType<IUserService, UserService>(new TransientLifetimeManager());
... and see if it creates a new UserService each time.