【问题标题】:Implement autofac in boostrapper (caliburn.micro) correctly在 boostrapper (caliburn.micro) 中正确实现 autofac
【发布时间】:2019-10-29 05:27:43
【问题描述】:

我想使用 Caliburn.Micro 和引导程序重新编写我的第一个小 C# 项目。在我的第一种方法中,我使用了 Autofac,但现在我被卡住了。如果没有 Caliburn,我可以从这样的 db 文件中检索我的员工(注意 scope.resolve 的东西——这就是我现在的问题):

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;
    }
}

现在我切换到 Caliburn.Micro incl。看起来像这样的引导程序(我想保留 LifeTimeScope 的东西)

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();
}

在应用程序启动时,我打开“CalendarViewModel”并获取相应的视图。我的视图包含一个菜单,该菜单通过以下实现在单击时打开第二个视图“EmployeeViewModel”:

private readonly IWindowManager _windowManager;
public CalendarViewModel(IWindowManager WindowManager)
{
    _windowManager = WindowManager;
}
public void OpenEmployeeView() => _windowManager.ShowWindow(new EmployeeViewModel());

现在我的问题是如何使用引导程序和使用“Lifetimescope”实现“IEmployeeRepository”将代码从一开始(仅限 Autofac)更改并包含在工作中。

我尝试过的:

我尝试像使用 WindowManager 一样包含“IEmployeeRepository”:

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;
    }
}

但是(您可能已经知道)我收到一个错误

CS7036 There is no argument given that corresponds to the required formal parameter

那么如何在 Bootstrapper 中正确实现 Autofac?很确定我的方法不是正确的方法:/

快速总结: (bootstrapper) --application start--> (CalendarViewModel) --menu item--> (EmployeeViewModel)

2019 年 10 月 29 日更新: 线

public EmployeeViewModel(IEmployeeRepository Emp)
{
    _emp = Emp;
}

引发错误。我猜是因为我的 OpenCommand

public void OpenEmployeeView() => _windowManager.ShowWindow(new EmployeeViewModel());

不会将任何 IEmployeeRepository 传递给我的 EmployeeViewModel。

2019 年 10 月 29 日第 2 期更新: 新的错误信息

System.InvalidOperationException: "一个无参数的默认构造函数 或一个匹配的签名(System.Int64 Id,System.String FirstName) Calendar.Database.Entities.EmployeeEntity 需要 物化”

被扔在里面 SqlRepository.cs(GetAll返回行抛出错误)

protected SqlRepository(IDbContext dbContext)
{
    DbContext = dbContext;
}

public IList<TEntity> GetAll()
{
    return DbContext.Connection.GetAll<TEntity>().ToList();
}

我做了什么: 引导程序.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;
    }
}

(我可以发布一个指向我的 Visual Studio 项目的链接……但不知道这里是否允许)

【问题讨论】:

  • 哪一行导致错误?你也可以看看sample 并尝试按照他实现一切
  • (更新了我最初的问题)我确实查看了示例并且我的 IWindowManager 正在按预期工作。我的猜测是我必须在“_windowsManager.ShowWindow”命令中传递 IEmployeeRepository 的实例。对我来说,在 CalendarViewModel 中定义 IEmployeeRepository 没有任何意义,将其传递给 open 命令并在新窗口中使用它(我已经在引导程序中定义了它:) .. 所以我真的需要一些帮助来正确实现它,不快也不脏
  • @Pavel 发现了问题……。在我的实体类深处有愚蠢的继承-.-您提出的解决方案有效
  • 没关系,我可以取消删除我的答案,你可以投票认为它有帮助

标签: c# mvvm autofac caliburn.micro


【解决方案1】:

你可以尝试使用

var employeeViewModel = IoC.Get<EmployeeViewModel>();
…
public void OpenEmployeeView() => _windowManager.ShowWindow(employeeViewModel);

使用注入的构造函数参数获取EmployeeViewModel 的实例。

另一个选项是将EmployeeViewModel 注入CalendarViewModel,如果它适合您的架构设计

【讨论】:

  • 好的,执行了您的建议,我似乎错过了其他内容。收到错误“DependencyResolutionException:无法解析类型'Calendar.Database.DbContext.DbContext',因为无法找到它所属的生命周期范围。此注册公开了以下服务:-Calendar.Database.DbContext.IDbContext ”。 IDbContext 的实现看起来像这样builder.RegisterType&lt;DbContext&gt;().As&lt;IDbContext&gt;() .InstancePerRequest(); 有什么想法吗?
  • 请用这个细节更新你的问题,你也可以根据autofac docsInstancePerRequest() for IDbContext 更改为InstancePerLifetimeScope()
  • 更新了我最初的帖子。非常感谢您的耐心和帮助!!
猜你喜欢
  • 2013-12-02
  • 2011-10-15
  • 1970-01-01
  • 2023-03-23
  • 2019-07-05
  • 2016-02-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多