Unity + EntityFramework + PRISM - "Resolution of the dependency failed" - c#

Im new on Unity/EF world and im getting a Error when i execute my test new project.
I have a Prism bootstrap first:
class Bootstrapper : UnityBootstrapper
{
protected override DependencyObject CreateShell()
{
return new Shell();
}
protected override void InitializeShell()
{
base.InitializeShell();
Application.Current.MainWindow = (Window)this.Shell;
Application.Current.MainWindow.Show();
}
protected override void ConfigureContainer()
{
base.ConfigureContainer();
this.Container
.RegisterType<IDataContextAsync, SistemaContext>(new ContainerControlledLifetimeManager())
.RegisterType<IUnitOfWorkAsync, UnitOfWork>(new ContainerControlledLifetimeManager())
.RegisterType<IRepositoryAsync<Cliente>, Repository<Cliente>>()
.RegisterType<IClienteService, ClienteService>();
}
protected override void ConfigureModuleCatalog()
{
base.ConfigureModuleCatalog();
ModuleCatalog moduleCatalog = (ModuleCatalog)this.ModuleCatalog;
moduleCatalog.AddModule(typeof(CadastroModule.CadastroModule));
}
}
And other project "CadastroModule" with the CadastroModule:
public class CadastroModule : IModule
{
private readonly IRegionManager regionManager;
public CadastroModule(IRegionManager regionManager)
{
this.regionManager = regionManager;
}
public void Initialize()
{
this.regionManager.RegisterViewWithRegion("MainRegion", typeof(Views.CadastroCliente));
}
}
Thats my EF Context:
public class SistemaContext : Sistema.Common.Repository.DataContext
{
static SistemaContext()
{//I dont know what to do here!
//Database.SetInitializer<SistemaContext>(new MigrateDatabaseToLatestVersion<SistemaContext, Sistema.DataAccess.Migrations.Configuration>());
}
public SistemaContext()
: base("Name=ContactsDb")
{
}
public DbSet<Cliente> Cliente { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new Sistema.DataAccess.Mapping.ClienteConfig());
modelBuilder.Configurations.Add(new Sistema.DataAccess.Mapping.EnderecoConfig());
}
}
I need the "MigrateDatabaseToLatestVersion" for automatic migrations.
The View:
public partial class CadastroCliente : UserControl
{
private readonly IClienteService _clienteService;
private readonly IUnitOfWork _unitOfWork;
public CadastroCliente()
{
InitializeComponent();
}
public CadastroCliente(IClienteService clienteService, IUnitOfWork unitOfWork)
{
_clienteService = clienteService;
_unitOfWork = unitOfWork;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
dgv.DataContext = _clienteService.ClienteOrdenadoNome();
}
}
UPDATE 1 IF i take out the IUnitOfWork it runs!:
public partial class CadastroCliente : UserControl
{
private readonly IClienteService _clienteService;
private readonly IUnitOfWork _unitOfWork;
public CadastroCliente()
{
InitializeComponent();
}
public CadastroCliente(IClienteService clienteService)
{
_clienteService = clienteService;
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
dgv.DataContext = _clienteService.ClienteOrdenadoNome();
}
}
Im using a Generic unit of Work repository located here: Link
And the Error is this:
At the time of the exception, the container was:
Resolving CadastroModule.Views.CadastroCliente,(none)
Resolving parameter \"unitOfWork\" of constructor CadastroModule.Views.CadastroCliente(Sistema.Service.IClienteService clienteService, Sistema.Common.Repository.UoW.IUnitOfWork unitOfWork)
Resolving Sistema.Common.Repository.UoW.IUnitOfWork,(none)
I detected when the UnitOfWork is taking the context
public class UnitOfWork : UnitOfWorkAsync
public UnitOfWork(IDataContextAsync dataContext) { _dataContext = dataContext; }
The dataContext return a internal exception exception:
The context cannot be used while the model is being created.
This exception may be thrown if the context is used inside the OnModelCreating method or if the same context instance is accessed by multiple threads concurrently.
Note that instance members of DbContext and related classes are not guaranteed to be thread safe
What im doing wrong?

Problem resolved after many days...
Internaly of the RepositoryFramework that im using, the EntityClasses need to inherit from a class named Entity:
public abstract class Entity : IObjectState
{
[NotMapped]
public ObjectState ObjectState { get; set; }
}
A child "Complex"(Entity framework Mapping ComplexTypeConfiguration<*>) class, was not inherited.
The error was not the UNIT/PRISM, was the repository itself that im using.
To resolve that i created a new project using no Modularity PRISM to be more simple to find where the error is comming.
So... my problem was resolved by putting the ": Entity" on my Child class:
public class Endereco : Entity //HERE
{
public string Rua { get; set; }
public int Numero { get; set; }
}

Related

MvvmCross usage of IMvxMessenger

I want to use the IMvxMessenger Plugin, but i cant initialize a viewmodel where I want to use it.
my Core.ViewModels
public class DataViewModel : MvxNavigationViewModel
{
protected readonly IMvxMessenger _messenger;
public DataViewModel(IMvxLogProvider logProvider, IMvxNavigationService navigationService, IMvxMessenger messenger)
: base(logProvider, navigationService)
{
this._messenger = messenger;
}
}
my WPFCore.ViewModels
public class DataViewModel : Core.ViewModels.DataViewModel
{
public DataViewModel(IMvxLogProvider logProvider, IMvxNavigationService navigationService, IMvxMessenger messenger)
: base(logProvider, navigationService, messenger)
{}
protected new void SaveDyno()
{
var message = new Core.Models.MvxReloaderMessage(this, this.Dyno);
this._messenger.Publish(message);
}
}
my messenger model
public class MvxReloaderMessage
: MvxMessage
{
public DynoModel Dyno
{
get;
private set;
}
public MvxReloaderMessage(object sender, DynoModel dyno)
: base(sender)
{
this.Dyno = dyno;
}
}
The error
"Failed to resolve parameter for parameter messenger of type IMvxMessenger when creating WPFCore.ViewModels.DataViewModel. You may pass it as an argument"
I also tried some Initialization, but it doesnt work or show some errors;
Mvx.RegisterType<IMvxMessenger, MvxReloaderMessage>();
Mvx.IoCProvider.RegisterSingleton<MvvmCross.Plugin.Messenger.IMvxMessenger>(new Core.Models.MvxReloaderMessage());
Mvx.IoCProvider.Resolve<MvvmCross.Plugin.Messenger.IMvxMessenger>();
Please make sure the plugin has been loaded. You can do that by overriding LoadPlugins in Setup.cs and add:
pluginManager.EnsurePluginLoaded<MvvmCross.Plugin.Messenger.Plugin>();

Prism 7.2 How to inject an instance into ViewModel another Module

i'm a new in a development of WPF applications with PRISM and AKKA.NET frameworks.
In my code for Shell Window I made an instance of ActorSystem.
public partial class App
{
private ActorSystem appActorSystem;
protected override Window CreateShell()
{
return Container.Resolve<MainWindow>();
}
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
appActorSystem = ActorSystem.Create(System.Reflection.Assembly.GetEntryAssembly()?.GetName().Name);
containerRegistry.RegisterInstance(appActorSystem);
}
protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
{
moduleCatalog.AddModule<CommandBar.CommandBarModule>();
}
protected override void OnExit(ExitEventArgs e)
{
appActorSystem.Terminate();
appActorSystem.Dispose();
base.OnExit(e);
}
}
The instance will be registered in DI Container (Unity) after creation.
In my application i have also a module.
public class CommandBarModule : IModule
{
private IContainerProvider _containerProvider;
public void OnInitialized(IContainerProvider containerProvider)
{
_containerProvider = containerProvider;
var appActorSystem = _containerProvider.Resolve<ActorSystem>();
var regionManager = _containerProvider.Resolve<IRegionManager>();
regionManager.RegisterViewWithRegion(regionNames.CommandBar, typeof(ViewA));
}
public void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterForNavigation<ViewA>();
}
}
I want to get the instance of the Actorsystem in the module. It works fine in CommandBarModule Class.
But I want also to get the instance of my Actorsystem in the ViewModel of the module...
public class ViewAViewModel : BindableBase
{
private string _message;
public string Message
{
get { return _message; }
set { SetProperty(ref _message, value); }
}
public ViewAViewModel()
{
Message = "test";
}
}
My First Idea was, that i can do injection of IContainerProvider into the constructor of the ViewModel, like this:
public class ViewAViewModel : BindableBase
{
private IContainerProvider _containerProvider;
private string _message;
public string Message
{
get { return _message; }
set { SetProperty(ref _message, value); }
}
public ViewAViewModel(IContainerProvider containerProvider)
{
_containerProvider = containerProvider;
var appActorSystem = _containerProvider.Resolve<ActorSystem>();
Message = "test";
}
}
But it doesn't work...
Could you please explain me how to do it right?
Inject the dependency, not the container:
public ViewAViewModel(ActorSystem appActorSystem)
{
Message = "test";
}
It does not matter in which module a service is registered and where it is resolved, as long as it's resolved after being registered.

Activation error with IEventAggregator Prism

I am using Prism in my WPF. When I add IEventAggregator as a parameter to the ViewModel constructor I get this error: An exception of type 'Microsoft.Practices.ServiceLocation.ActivationException' occurred in Microsoft.Practices.ServiceLocation.dll.
Additional information: Activation error occurred while trying to get instance of type Object, key "CategoriesView"
The exception is triggered in this line:
private void NavigateToCategoriesRadioButton_Click(object sender, RoutedEventArgs e)
{
this.regionManager.RequestNavigate(RegionNames.ConfigurationContentRegion, categoriesViewUri);
}
where categoriesViewUri is:
private static Uri categoriesViewUri = new Uri("/CategoriesView", UriKind.Relative);
This is my view model class:
[Export]
public class CategoriesViewModel : BindableBase
{
private readonly IRegionManager regionManager;
private readonly IEventAggregator eventAggregator;
private readonly IConfigurationCategoriesService categoriesService;
private readonly ObservableCollection<Category> categoriesCollection;
private readonly ICollectionView categoriesView;
private readonly DelegateCommand<object> deleteCategoryCommand;
[ImportingConstructor]
public CategoriesViewModel(IEventAggregator eventAggregator, IConfigurationCategoriesService categoriesService, IRegionManager regionManager)
{
this.categoriesService = categoriesService;
this.regionManager = regionManager;
this.eventAggregator = eventAggregator;
this.deleteCategoryCommand = new DelegateCommand<object>(this.DeleteCategory, this.CanDeleteCategory);
this.categoriesCollection = new ObservableCollection<Category>(categoriesService.GetCategories());
this.categoriesView = new ListCollectionView(this.categoriesCollection);
this.categoriesView.CurrentChanged += (s, e) => this.deleteCategoryCommand.RaiseCanExecuteChanged();
}
public ICollectionView Categories
{
get { return this.categoriesView; }
}
public ICommand DeleteCategoryCommand
{
get { return this.deleteCategoryCommand; }
}
private void DeleteCategory(object ignored)
{
var category = this.categoriesView.CurrentItem as Category;
if (category != null)
{
categoriesService.DeleteCategory(category);
}
}
private bool CanDeleteCategory(object ignored)
{
return true;
}
}
It looks like CatagoriesViewModel cannot get an instance of IEventAggregator on the constructor but this is done automatically by Prism, isn't it? In the example I have from Prism Documentation (StockTraderRI_Desktop) I donĀ“t see anywhere where the EventAggregator is instantiated. Can anyone see what am I getting wrong? Thanks in advance
Editted:
The Navitagion item view is registerd in the CategoriesModule class:
[ModuleExport(typeof(CategoriesModule))]
public class CategoriesModule : IModule
{
[Import]
public IRegionManager regionManager;
public void Initialize()
{
this.regionManager.RegisterViewWithRegion(RegionNames.ConfigurationNavigationRegion, typeof(CategoriesNavigationItemView));
}
}
And CategoriesView code-behind is:
[Export("CategoriesView")]
public partial class CategoriesView : UserControl
{
public CategoriesView()
{
InitializeComponent();
}
[Import]
public IRegionManager regionManager;
[Import]
public CategoriesViewModel ViewModel
{
get { return this.DataContext as CategoriesViewModel; }
set { this.DataContext = value; }
}
}
I solved this issue adding the following using statement:
using Microsoft.Practices.Prism.PubSubEvents;
instead of
using Prism.Events;
I also switched to Unity instead of MEF by recommendation on this site.

Passing data from one VM to another VM, using Unity and prism EventAggregator

Trying to pass data from one ViewModel to another using prism EventAggregator, but when I debug on the subscriber, the data is null.
Using version 5.0 of prism.
Update
Okay, I have tried implement the EventAggregator using prism 5.0 version. It still dosen't work, but here is what I have done.
1: Create event class
public class RoomsSelectedEvent : PubSubEvent<ObservableCollection<Room>>
{
}
2: Inject IEventAggregator on publisher ViewModel (BookingViewModel)
public class BookingViewModel : INotifyPropertyChanged, IViewBookingViewModel
{
//aggregator
protected readonly IEventAggregator _eventAggregator;
//commands
public ICommand ContinueCommand { get; set; }
public ObservableCollection<Room> RoomsList { get; private set; }
public ObservableCollection<RoomList> DropDownRooms { get; private set; }
public ObservableCollection<CustomerList> DropDownCustomers { get; private set; }
//enities
private readonly IDialogService<ContactDetailsView> _dialogServiceContactView;
private readonly IGetRoomsService _getRoomsService;
public BookingViewModel(IDialogService<ContactDetailsView> dialogServiceContactview, IGetRoomsService GetRoomsService, IEventAggregator eventAggregator)
{
// Injection
_dialogServiceContactView = dialogServiceContactview;
_getRoomsService = GetRoomsService;
_eventAggregator = eventAggregator;
//commands
ContinueCommand = new RelayCommand(ContinueCommand_DoWork, () => true);
}
// Continue Command
public void ContinueCommand_DoWork(object obj)
{
ObservableCollection<Room> RoomsSelected = new ObservableCollection<Room>();
RoomsSelected = _getRoomsService.FilterSelectedRooms(RoomsList);
//Publish event:
_eventAggregator.GetEvent<RoomsSelectedEvent>().Publish(RoomsSelected);
// Open new dialog
_dialogServiceContactView.ShowDialog();
}
}
3: Inject IEventAggregator in subscriber viewModel (ContactViewModel)
public class ContactViewModel : IViewContactViewModel, INotifyPropertyChanged
{
//aggregator
protected readonly IEventAggregator _eventAggregator;
//properties
public ObservableCollection<Room> SelectedRooms { get; set; }
public ContactViewModel(IEventAggregator eventAggregator)
{
//Injection
_eventAggregator = eventAggregator;
//Subscripe to event
_eventAggregator.GetEvent<RoomsSelectedEvent>()
.Subscribe((data) => { SelectedRooms = data; });
}
public ObservableCollection<Room> Rooms
{
get { return SelectedRooms; }
set { SelectedRooms = value; NotifyPropertyChanged(); }
}
}
I have read it's maybe because of the IEventAggregator is not the same in both ViewModels. I'm using Unity to inject it like this code:
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
//view & viewModels
_container = new UnityContainer();
_container.RegisterType<IViewMainWindowViewModel, MainWindow>();
_container.RegisterType<IViewMainWindowViewModel, MenuViewModel>();
_container.RegisterType<IViewBookingViewModel, BookingView>();
_container.RegisterType<IViewBookingViewModel, BookingViewModel>();
_container.RegisterType<IViewContactViewModel, ContactDetailsView>();
_container.RegisterType<IViewContactViewModel, ContactViewModel>();
_container.RegisterType<IGetRoomsService, GetRoomsService>();
_container.RegisterType<IPostReservationService, PostReservationService>();
_container.RegisterType<IGetReservationsListService, GetReservationsListService>();
//types
_container.RegisterType<IEventAggregator, EventAggregator>(new ContainerControlledLifetimeManager());
_container.RegisterType(typeof(IDialogService<>), typeof(DialogService<>));
_container.Resolve<MainWindow>().Show();
}
Found that I need to add the ContainerControlledLifetimeManager, but it still wont work.
When I debug in the subscriber viewModel, I can see that there is an event inside the instance, like on the image:
It wont catch it , thats the problem :(
Today I tried delete all packages I installed (prism 5.0) and go for the Prism.Core (6.1 version)
That resulted in the same, I can see when I debug that the event in published, but when I subscribe, it's still null.

Caliburn Micro - Share data between ViewModels

Starting from the Caliburn Micro "Simple MDI" example. I would like to achieve the following:
I would like to share the reference of a class between the ViewModels. The shareme.count should be passed as reference to all the ViewModels. This would allow me to change it from within each ViewModel.
How can I achieve this close to Caliburn Micro convention?
ShellViewModel.cs
public class ShellViewModel : Conductor<IScreen>.Collection.OneActive {
SharedClass _shareme;
public SharedClass shareme {
get { return _shareme; }
set {
_shareme = value;
NotifyOfPropertyChange(() => shareme);
}
}
public ShellViewModel() {
shareme.count = 1;
}
public void OpenTab() {
ActivateItem(new TabViewModel {
DisplayName = "Tab " + shareme.count++
});
}
TabViewModel.cs
public class TabViewModel : Screen {}
AppBootstrapper.cs
public class AppBootstrapper : BootstrapperBase {
SimpleContainer container;
public AppBootstrapper() {
Initialize();
}
protected override void Configure() {
container = new SimpleContainer();
container.Singleton<IWindowManager, WindowManager>();
container.Singleton<IEventAggregator, EventAggregator>();
container.PerRequest<IShell, ShellViewModel>();
}
protected override object GetInstance(Type service, string key) {
var instance = container.GetInstance(service, key);
if (instance != null)
return instance;
throw new InvalidOperationException("Could not locate any instances.");
}
protected override IEnumerable<object> GetAllInstances(Type service) {
return container.GetAllInstances(service);
}
protected override void BuildUp(object instance) {
container.BuildUp(instance);
}
protected override void OnStartup(object sender, System.Windows.StartupEventArgs e)
{
DisplayRootViewFor<IShell>();
}
}
The will also serve as answer to your duplicate question.
EventAggregator isn't just for "events" you can message pass data to any or all viewmodels that are listening for message or event signature in question.
public class ViewModelA : Screen, IHandle<ShareMeMessageA>
{
private readonly IEventAggregator _events;
private int _sharemecount;
public class ViewModelA(IEventAggregator events){
_events = events;
_events.Subscribe(this);
}
//... other bits out for brevity
//-- EDIT --
public void SomeEventClick(){
_event.PublishOnUiThread(new ShareMeMessageB(){ ... etc ... });
}
protected override void Deactivated(bool close){
_events.Unsubscribe(this);
}
private void Handle(ShareMeMessageA msg)
{
if(msg != null)
sharemecount = msg.Count;
}
}
as this is just an example you don't have to pass the class object at all you can pass any type you want bool, int, float, etc..

Categories