Reputation: 389
I would like to re-code my first little C# project using Caliburn.Micro and the bootstrapper stuff. During my first approach I used Autofac but now I'm stuck. Without Caliburn I was able to retrieve my employees from a db file like this (mind the scope.resolve stuff -- thats my problem right now):
public ObservableCollection<EmployeeEntity> Employees
{
get
{
var container = ContainerConfig.Configure();
using (var scope = container.BeginLifetimeScope())
{
var test = scope.Resolve<IEmployeeRepository>();
_Employees = test.GetAll().ToObservable();
}
return _Employees;
}
set
{
_Employees = value;
}
}
Now I switched to Caliburn.Micro incl. bootstrapper which looks like this (I would like to keep the LifeTimeScope stuff)
protected override void Configure()
{
var builder = new ContainerBuilder();
builder.RegisterType<WindowManager>()
.AsImplementedInterfaces()
.SingleInstance();
builder.RegisterType<EventAggregator>()
.AsImplementedInterfaces()
.SingleInstance();
builder.RegisterType<CalendarViewModel>()
.SingleInstance();
builder.RegisterType<EmployeeViewModel>()
.SingleInstance();
builder.RegisterType<EmployeeRepository>().As<IEmployeeRepository>()
.InstancePerLifetimeScope();
Container = builder.Build();
}
On application start I open "CalendarViewModel" and get the corresponding view. My view contains a menu which opens a second view "EmployeeViewModel" on click with the following implementation:
private readonly IWindowManager _windowManager;
public CalendarViewModel(IWindowManager WindowManager)
{
_windowManager = WindowManager;
}
public void OpenEmployeeView() => _windowManager.ShowWindow(new EmployeeViewModel());
Now my problem is how to change and include the code from the beginning (Autofac only) to a working one using the bootstrapper and the implementation of "IEmployeeRepository" with "Lifetimescope".
What I have tried:
I tried to include "IEmployeeRepository" like I did with the WindowManager:
private ObservableCollection<EmployeeEntity> _Employees;
private readonly IEmployeeRepository _emp;
public EmployeeViewModel(IEmployeeRepository Emp)
{
_emp = Emp;
}
public ObservableCollection<EmployeeEntity> Employees
{
get
{
_Employees = _emp.GetAll().ToObservable();
return _Employees;
}
set
{
_Employees = value;
}
}
but (as you might already know) I get an error
CS7036 There is no argument given that corresponds to the required formal parameter
So how do I implement Autofac within Bootstrapper correctly? Quite sure that my way isn't the proper way to do it :/
Quick summary: (bootstrapper) --application start--> (CalendarViewModel) --menu item--> (EmployeeViewModel)
UPDATE 29.10.2019: The line
public EmployeeViewModel(IEmployeeRepository Emp)
{
_emp = Emp;
}
throws an error. I guess because my OpenCommand
public void OpenEmployeeView() => _windowManager.ShowWindow(new EmployeeViewModel());
does not pass any IEmployeeRepository to my EmployeeViewModel.
UPDATE 29.10.2019 No 2: new error message
System.InvalidOperationException: "A parameterless default constructor or one matching signature (System.Int64 Id, System.String FirstName) is required for Calendar.Database.Entities.EmployeeEntity materialization"
is thrown within SqlRepository.cs (GetAll return row throws the error)
protected SqlRepository(IDbContext dbContext)
{
DbContext = dbContext;
}
public IList<TEntity> GetAll()
{
return DbContext.Connection.GetAll<TEntity>().ToList();
}
What I did: Bootstrapper.cs
builder.RegisterType<EmployeeViewModel>()
.SingleInstance();
builder.RegisterType<DbContext>().As<IDbContext>()
.InstancePerLifetimeScope();
builder.RegisterType<EmployeeRepository>().As<IEmployeeRepository>()
.InstancePerLifetimeScope();
CalendarViewModel.cs
public void OpenEmployeeView() => _windowManager.ShowWindow(IoC.Get<EmployeeViewModel>());
EmployeeViewModel.cs
private readonly IEmployeeRepository _emp;
public EmployeeViewModel(IEmployeeRepository Emp)
{
_emp = Emp;
}
public ObservableCollection<EmployeeEntity> Employees
{
get
{
_Employees = _emp.GetAll().ToObservable();
return _Employees;
}
set
{
_Employees = value;
}
}
(I could post a link to my Visual Studio Project … but don't know if it is allowed here)
Upvotes: 0
Views: 716
Reputation: 23268
You can try to use
var employeeViewModel = IoC.Get<EmployeeViewModel>();
…
public void OpenEmployeeView() => _windowManager.ShowWindow(employeeViewModel);
to get instance of EmployeeViewModel
with injected constructor parameters.
Another option is inject the EmployeeViewModel
to CalendarViewModel
, if it fits your arhitecture design
Upvotes: 1