Wpf PRISM disposable module - wpf

I'm having a WPF application that is divided into PRISM modules.
I have a service that deals with some unmanaged resources, therefore it implements the IDisposable interface:
public class MyCacheService : IMyCacheService, IDisposable
{
...
}
I also have a CameraServicesModule which registers an IMyCacheService instance:
public class CameraServicesModule : IModule
{
public CameraServicesModule(IComponentsManager manager)
{
this.manager = manager;
}
public void Initialize()
{
...
var theCacheService = new MyCacheService();
this.manager.RegisterInstance(typeof(IMyCacheService), null, theCacheService);
}
}
The question is: how do I dispose of the service instance? I have to do it at the application closing, but right now the MyCacheService.Dispose() doesn't get called at the application shutdown (or any other point in time).
Should the CameraServicesModule implement IDisposable, too? Like this:
public class CameraServicesModule : IModule, IDisposable
{
public CameraServicesModule(IComponentsManager manager)
{
this.manager = manager;
}
public void Initialize()
{
...
this.theCacheService = new MyCacheService();
this.manager.RegisterInstance(typeof(IMyCacheService), null, theCacheService);
}
public void Dispose()
{
this.theCacheService.Dispose();
}
}
If so, the question is: how do I dispose of the module? If not, the question is: which way should I dipose the service of?
LocalFileSystemConfigurationManager configManager = new LocalFileSystemConfigurationManager(this.PathToSettings);
ComponentsManager compManager = new ComponentsManager(configManager, null, null);
Note: even if my module does implement IDisposable, disposing the componentsManager or configurationManager does not dispose the module.

OK, after consulting some senior developers I came to a conclusion that the most appropriate way to dispose of the service is to implement IDisposable on the module which creates the service instance:
public class CameraServicesModule : IModule, IDisposable
{
public CameraServicesModule(IComponentsManager manager)
{
this.manager = manager;
}
public void Initialize()
{
...
this.theCacheService = new MyCacheService();
this.manager.RegisterInstance(typeof(IMyCacheService), null, theCacheService);
}
public void Dispose()
{
this.theCacheService.Dispose();
}
}
Though the module implements IDisposable, we can leave it as it is, without manually calling Dispose. The module should exist until the apllication works (at least in my case), so all of the allocated resources are anyway freed up at the application close.

Related

Return a async list from SQL Server database and use in a datagrid WPF app

I'm currently facing a pretty strange behaviour I'm uncertain whether I do something wrong or not but here is the problem.
I try to return a list asynchronously from a repository and load it into a datagrid in a WPF application using Prism. When I return the list synchronously, it loads just fine, but as soon as I use it async the program run, but the interface will not display and no error is triggered.
If you need more info don't hesitate - thanks in advance.
Here is the code - shortened for simplicity:
The view
<UserControl>
<Grid>
<DataGrid ItemsSource="{Binding Products}" />
</Grid>
</UserControl>
The view model:
public class ProductViewModel : BindableBase, INavigationAware
{
private readonly IProductRepo _repo = new ProductRepo();
public ObservableCollection<Data.Models.Product> Products { get; set; }
public ProductViewModel()
{
Products = new ObservableCollection<Data.Models.Product>(this._repo.GetAll().Result);
}
}
The DbContext:
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext()
{
}
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
{
}
public DbSet<Product> Products { get; set; }
}
The IProductRepo interface:
public interface IProductRepo
{
Task<List<Product>> GetAll();
}
The ProductRepo class that implements IProductRepo interface:
public class ProductRepo : IProductRepo
{
private readonly ApplicationDbContext _context;
public ProductRepo()
{
this._context = new ApplicationDbContext();
}
public async Task<List<Product>> GetAll()
{
return await this._context.Products.ToListAsync();
}
}
I tried to create an async private method inside the view model to load the data, then call the function in the constructor, but this doesn't work.
public void LoadData()
{
List<Data.Models.Product> ProductFromDB = this._repo.GetAll().Result;
foreach (var p in ProductFromDB)
{
Products.Add(p);
}
}
If you really believe you need to load all data on initialization, then a simple solution would be to load the data from the view.
The point is that calling Task.Result on an asynchronous method will very likely cause a deadlock.
Additionally, a long-running constructor can interfere with or even break the initialization routine of the controls (UI).
Furthermore, not awaiting an async method will lead to undefined behavior as the caller's context continues to execute while the the async method is still running and pending to return.
For example, the caller can now leave the method scope prematurely and the async method can never return.
It's more than best practice to ensure that constructors return fast and are light weight. They shouldn't allocate expensive resources and should not start background threads, which is generally a surprise for the caller.
A constructor is not meant to execute any kind of operations except to initialize its instance members to a reasonable default. Even advanced instance configuration should take place outside the constructor.
Also be aware that ToList or ToListAsync will force the query to be evaluated client-side. This can hurt significantly the application performance especially when the table is big. On the other hand, the database is highly optimized to execute queries efficiently, which makes server-side query evaluation favorable.
Since you are only fetching the complete table, it doesn't really matter in your scenario. But in case of advanced queries it can make the difference.
The following example shows how to execute the asynchronous initialization from the view. Depending on the exact scenario other solution can be applied.
The example assumes that the ProductViewModel is created and exposed by the main view model class. But the caller doesn't matter. Just let the control that creates the instance call the long-running initialization routine:
IInitializable.cs
Introducing as dedicated interface even allows to anonymously call all async and long-running initialization routines on application composition, for example in a dependency injection context.
This generally works in any composition context, for example when using composition to manage the hierarchy of classes.
In case of this example, the composition root of all view models would be the main view model class.
public interface IInitializable
{
Task<bool> InitializeAsync();
bool IsInitialized { get; }
}
ProductViewModel.cs
public class ProductViewModel : BindableBase, INavigationAware, IInitializable
{
private readonly IProductRepo _repo = new ProductRepo();
public ObservableCollection<Data.Models.Product> Products { get; }
public bool IsInitialized { get; private set; }
public ProductViewModel()
{
// Only initialize to a reasonable default.
// Expensive initialization is deferred.
this.Products = new ObservableCollection<Data.Models.Product>();
}
// Allow to defer long-running initialization routines.
// Such routines can be both, synchronous or asynchronous.
public async Task<bool> InitializeAsync()
{
if (this.IsInitialized)
{
return;
}
// You should rename 'GetAll' to 'GetAllAsync'
List<Product> allProducts = await this._repo.GetAll();
allProducts.ForEach(this.Products.Add);
this.IsInitialized = true;
return this.IsInitialized;
}
}
MainWindowViewModel.cs
public class MainWindowViewModel : BindableBase, INavigationAware, IInitializable
{
public ProductViewModel ProductViewModel { get; }
public bool IsInitialized { get; private set; }
private IList<IInitializable> InitializableDependencies { get; }
public MainWindowViewModel()
{
// The container for polymorphic and anonymous iteration
this.InitializableDependencies = new List<IInitializable>();
// Create the composition tree.
// Because expensive initialization of dependencies is deferred,
// the type construction is cheap and guaranteed to return fast.
this.ProductViewModel = new ProductViewModel();
// Store potential IInitialize implementation for later initialization.
// This allows to use polymorphism to improve the code.
// Additionally, we avoid explicit knowledge whether the instantiated type implements this interface or not.
// This enhances extensibility significantly.
TryAddInitializable(this.ProductViewModel);
}
// Store IInitializable implementations anonymously for later iteration.
private bool TryAddInitializable(object instance)
{
if (instance is IInitializable initializableInstance)
{
this.InitializableDependencies.Add(initializableInstance);
return true;
}
return false;
}
// Allow to defer long-running initialization routines.
// Such routines can be both, synchronous or asynchronous.
public async Task<bool> InitializeAsync()
{
if (this.IsInitialized)
{
return;
}
// Cascade IInitializeAsync calls. In context of dependency injection
// this wouldn't be necessary as the IoC container would allow to filter
// all types that implement IInitializable to call InitializeAsync on each type explicitly.
// Because we only need to know the IINitializable interface, the calls are anonymous, allowing easy extension of the code.
foreach (IInitializable initializableInstance in this.InitializableDependencies)
{
// Trigger the cascade of InitializeAsync calls,
// given that the ProductViewModel is the composition root of other view model classes
// or classes that implement IInitializable.
bool isSuccesfullyInitialized = await initializableInstance.InitializeAsync();
}
this.IsInitialized = true;
return this.IsInitialized;
}
}
MainWindow.xaml.cs
The idea is to start the deferred initialization from the FrameworkElement.Loaded event of a reasonable element (in this case this is the MainWindow).
If ProductViewModel is created by another view model class, then you would have to let this view model implement IInitializable too and cascade the InitializeAsync method calls.
partial class MainWindow : Window
{
private MainWindowViewModel ViewModel { get; }
public MainWindow()
{
InitializeComponent();
this.ViewModel = new MainWindowViewModel();
this.DataContext = this.ViewModel;
this.Loaded += OnLoaded;
}
// Use the Loaded event to execute long-running or resource intensive routines
// outside the constructor.
// Define handler as 'async void' to await the async method calls.
private async void OnLoaded(object sender, RoutedEventArgs e)
{
if (this.ViewModel is IInitializable initializableViewModel)
{
// Trigger the cascade of InitializeAsync calls,
// given that the MainWindowViewModel is the composition root of all view model classes
// or classes that implement IInitializable in general.
_ = await initializableViewModel.InitializeAsync();
}
}
}
MainWindow.xaml
<Window>
<ProductView DataGridItemsSource="{Binding ProductViewModel.Products}" />
</Window>

Unity Bootstrapper my configure container does not work when call a View Model [duplicate]

This question already has answers here:
Prism 6 with Unity - resolving view models for views without naming convention
(2 answers)
Closed 6 years ago.
I use prism 6.1. I set up the Unity configuration in the method ConfigureContainer of Bootstrapper class. But, when the Prism framework try to call the View Model, it can't create this, and throw the exception 'No parameterless constructor defined for this object.'.
Bootstrapper.cs
public class Bootstrapper: UnityBootstrapper
{
...
protected override void ConfigureContainer()
{
base.ConfigureContainer();
this.Container.RegisterType<IMyService, MyService>(new ContainerControlledLifetimeManager());
this.Container.RegisterType<MyFormViewModel>(new ContainerControlledLifetimeManager());
}
...
}
MyFormModule.cs
public class MyFormModule : IModule
{
private readonly IRegionViewRegistry regionViewRegistry;
public SkypeActionModule(IRegionViewRegistry registry)
{
this.regionViewRegistry = registry;
}
public void Initialize()
{
regionViewRegistry.RegisterViewWithRegion("MainRegion", typeof(Views.MyFormView));
}
}
MyFormViewModel.cs
public class MyFormViewModel : BindableBase
{
private readonly IMyService myService;
public SkypeActionViewModel(IMyService myService)
{
this.myService = myService;
}
...
}
In this line throw the exception:
regionViewRegistry.RegisterViewWithRegion("MainRegion", typeof(Views.MyFormView));
In the prism documentation explains how to configurate unity, but this is in the Module class (in my case is MyFormModule). I don't understand that because in this way, I need to configurate that in each module, and I haven't the object this.container.RegisterType in my module class.
In others links, I found some configuration similar to "MEF" configuration, where the "DI" configuration are in the ConfigureContainer method. But it doesn't work for my, or something missing in my configuration.
Edit
I include the container in my module class. But I have the same problem. I suppose that is normal, because the problem is when Prism create the view model class MyFormViewModel.
public class MyFormModule : IModule
{
private readonly IRegionViewRegistry regionViewRegistry;
private readonly IUnityContainer container;
public MyFormModule(IRegionViewRegistry registry, IUnityContainer container)
{
this.regionViewRegistry = registry;
this.container = container;
}
public void Initialize()
{
this.container.RegisterType<IMyService, MyService>(new ContainerControlledLifetimeManager());
this.container.RegisterType<MyFormViewModel>();
this.container.RegisterType<MyFormView>();
regionViewRegistry.RegisterViewWithRegion("MainRegion", typeof(MyFormView));
}
}
Edit
Solution: I found the solution in this question on stackoverflow
Create the method BindViewModelToView on Bootstrap class:
public void BindViewModelToView<TViewModel, TView>()
{
ViewModelLocationProvider.Register(typeof(TView).ToString(), () => Container.Resolve<TViewModel>());
}
and then, in the method ConfigureViewModelLocator in Bootstrap class call all view models it to bind with views:
protected override void ConfigureViewModelLocator()
{
BindViewModelToView<ViewAVM, ViewA>();
BindViewModelToView<ViewAVM, ViewB>();
}
How do you tell prism to create the view model? Are you using ViewModelLocator.AutoWireViewModel="True"?
If so, you want to do something like
ViewModelLocationProvider.SetDefaultViewModelFactory( type =>
{
return Container.Resolve(type);
});
in the bootstrapper to make sure that your container is used for resolving the view model...

Instantiate IUnitOfWork for each ViewModels in WPF/Prism app

I have lots of repositories like this:
public class PersonRepository : IPersonRepository
{
private readonly IUnitOfWork _unitOfWork;
public PersonRepository(IUnitOfWork instance)
{
_unitOfWork = instance;
}
//Remove, Get methods...
public void Add(Person p)
{
_unitOfWork.Context.People.Add(p);
}
}
and Unit of work class like this:
public class UnitOfWork : IUnitOfWork, IDisposable
{
public UnitOfWork(){ }
private readonly HezarehContext _context = new HezarehContext();
public HezarehContext Context
{
get
{
return _context;
}
}
public int Save()
{
return _context.SaveChanges();
}
public void Initialize()
{
Context.Database.Initialize(false);
}
#region IDisposable Members
public void Dispose()
{
_context.Dispose();
}
#endregion
}
Now i want each time my ViewModels gets resolved, a new IUnitOfWork instantiated. Most of my ViewModels are like this:
public class PeopleMainViewModel : NotificationObject
{
// both of repositories must have same instance of IUnitOfWork
private readonly IPersonRepository _personRepository = ServiceLocator.Current.GetService<IPersonRepository>();
private readonly ICategoryRepository _categoryRepository = ServiceLocator.Current.GetService<ICategoryRepository>();
public PeopleMainViewModel()
{
InitializeView();
}
// add, edit, remove commands ...
}
ViewModels always gets resolved using Unity Container like this:
Container.RegisterType<IPersonRepository, PersonRepository>();
// resolve in InjectionProperty...
Container.RegisterType<Object, PeopleMainView>("PeopleMainView", new InjectionProperty(PeopleMainView.DataContextProperty.Name, Container.Resolve<PeopleMainViewModel>();
And my question is, How and Where i Register my ViewModels and IUnitOfWork to have IUnitOfWork instance for each of them?
If I understand your question, just register your IUnitOfWork the same way (and same place) you register the repository in your above example. You don't need to register your ViewModels based on your current design since you aren't using an Interface.
Container.RegisterType<IUnitOfWork, UnitOfWork>();
And continue to have your repositories accept the IUnitOfWork in the constructor. This will allow Unity to use constructor injection to provide a new instance of IUnitOfWork each time it resolves a repository. By default, you'll get a new instance of the IUnitOfWork each time. If you'd like to have a singleton IUnitOfWork, you would have to say so when you register the IUnitOfWork like this:
Container.RegisterType<IUnitOfWork, UnitOfWork>(new ContainerControlledLifetimeManager());
If you want to read up on Lifetime Managers, you can do so here.
I would also recommend changing your ViewModels to take the repositories in as Constructor Parameters, like this if you are going to Resolve them (so Unity will do the work without you referencing the ServiceLocator directly)
public PeopleMainViewModel(IPersonRepository personRepo, ICategoryRepository categoryRepo)
{
...
}
Update:
There is another solution here in unity.codeplex discussions.
I finally found a solution.
There is a feature in Unity container that let you pass parameters while resolving a Type. by changing constructor of ViewModels to this:
public class PeopleMainViewModel : NotificationObject
{
private readonly IPersonRepository _personRepository = null;
private readonly ICategoryRepository _categoryRepository = null;
public PeopleMainViewModel(IUnityContainer container, IUnitOfWork unitOfWork)
{
// now both of repositories have same instance of IUnitOfWork
_personRepository = container.Resolve<IPersonRepository>(new ParameterOverride("unitOfWork", unitOfWork));
_categoryRepository = container.Resolve<ICategoryRepository>(new ParameterOverride("unitOfWork", unitOfWork));
InitializeView();
}
// add, edit, remove commands ...
}
problem solved. now _personReposiotry and _categoryRepository have reference to same instance of unitOfWork.

MVVMLight ViewModelLocator registering dataservice

This question might look naive, but I couldn't understand this code in the ViewModelLocator.cs file:
static ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
if (ViewModelBase.IsInDesignModeStatic)
{
SimpleIoc.Default.Register<IDataService, Design.DesignDataService>();
}
else
{
SimpleIoc.Default.Register<IDataService, DataService>();
}
SimpleIoc.Default.Register<MainViewModel>();
}
I see that we use a DataService to get data (from WCF service for example) and assigning it to the MainViewModel. But what if I'm registering more than one ViewModel? like this:
static ViewModelLocator()
{
....
SimpleIoc.Default.Register<MainViewModel>();
SimpleIoc.Default.Register<Page2ViewModel>();
}
and let's say I have another DataService (DataService2 for example), but this one I'll use with the Page2ViewModel. how can I do that?
Also, if someone can help me (or even give me a link to read) about the above code. I have no clue what it means.
You are not assigning any IDataService to the MainViewModel here. You are registering a type mapping, so your container will be aware that it should return a DataService whenever an IDataService required.
This is related to dependency injection http://en.wikipedia.org/wiki/Dependency_injection
The DI container auto-wires the dependencies, so when you need a specific type, you can call
ServiceLocator.Current.GetInstance<IDataService>()
or
ServiceLocator.Current.GetInstance<MainViewModel>()
etc. If it can build it (so you registered your types), it will resolve the full dependency graph for you.
For example, if your MainViewModel has a constructor dependency on IDataService, and you are not in design mode, a DataService will be injected to the MainViewModel constructor. Don't be afraid from the buzzword injected, it is just a call to the MainViewModel constructor with the appropriate parameters :).
So, MainViewModel will not interference with Page2ViewModel here.
I made a simple sample for you to demonstrate what happens (I used Unity, http://unity.codeplex.com/ , but the syntax is almost the same):
class Program
{
static void Main(string[] args)
{
var container = new UnityContainer();
container.RegisterType<IService, Service1>();
container.RegisterType<IService, Service2>("MySpecificService");
container.RegisterType<IRepository, Repository>();
ServiceLocator.SetLocatorProvider(() => new UnityServiceLocator(container));
var viewModel = ServiceLocator.Current.GetInstance<MainViewModel>();
viewModel.Foo();
}
}
interface IService
{
}
interface IRepository
{
}
class Service1 : IService
{
public Service1(IRepository repository)
{
Console.WriteLine("Service1 created");
}
}
class Service2 : IService
{
public Service2()
{
Console.WriteLine("Service2 created");
}
}
class Repository : IRepository
{
public Repository()
{
Console.WriteLine("Repository created");
}
}
class MainViewModel
{
public MainViewModel(IService service)
{
Console.WriteLine("MainViewModel created");
}
public void Foo()
{
var specificService = ServiceLocator.Current.GetInstance<IService>("MySpecificService");
}
}
the output is:
Repository created
Service1 created
MainViewModel created
Service2 created
Because you need a MainViewModel (maybe in SimpleIoC you need to register MainViewModel too, in Unity, it can resolve concrete classes without mapping), the container trying to create one, but it realizes that MainViewModel needs an IService, and it finds the default one from the mapping, which is Service1, but it realizes that Service1 needs an IRepository, and it finds the default one, so it can pass a Repository to the Service1 constructor, then the Service1 instance to the MainViewModel constructor. All the dependencies resolved.
The Foo call is an example how you can register more than one type to the same interface. Dependency injection is a much more bigger topic, but auto-wiring is an important part of it.

Prism v4, MEF service

I have a WPF windows application that uses the ms ribbon control for the menu. In my infrastructure project I want to have a shared service that will be referenced in all modules. Each module will then use that service to define what menu items should be displayed for the module.
I read this Prism+MEF: delayed a service export from prism-module but can't get my other modules to recognize the service.
The service
namespace Infrastructure
{
[ModuleExport("InfModule", typeof(InfModule), InitializationMode = InitializationMode.WhenAvailable)]
[PartCreationPolicy(CreationPolicy.Shared)]
public class InfModule : IModule
{
[Export(typeof(IMenuService))]
public IMenuService MenuService { get; private set; }
public void Initialize()
{
MenuService = new MenuService();
MenuService.AddItem("test");
}
}
}
The module
namespace Classic
{
[ModuleExport("Classic", typeof(Classic), InitializationMode = InitializationMode.WhenAvailable)]
[ModuleDependency("InfModule")]
public class Classic : IModule
{
private IRegionManager _regionManager;
[Import(typeof(IMenuService))]
private IMenuService menuService { get; set; }
[ImportingConstructor]
public Classic(IRegionManager regionManager)
{
this._regionManager = regionManager;
// This shows as true
Debug.WriteLine(menuService == null);
}
public void Initialize()
{
_regionManager.RegisterViewWithRegion("RibbonRegion", typeof(Views.RibbonTabMenu));
// This shows as true
Debug.WriteLine(menuService == null);
}
}
}
I would have expected one of the debug lines to output as false since its imported. Any idea's what I'm missing?
Property imports will never be set while running the constructor, since you can't set properties on an object until it's constructed.
The other problem is that in InfModule, you are setting the exported value too late. MEF only looks at the value for an export once, after that it caches the value and doesn't call the getter again. In this case it is getting the export before Initialize() is called. The logic to set the export needs to either run from the constructor or from code in the property getter.

Resources