如何使用 caliburn micro 在 Wpf 中注入 EF DbContext

Posted

技术标签:

【中文标题】如何使用 caliburn micro 在 Wpf 中注入 EF DbContext【英文标题】:How to Inject EF DbContext in Wpf using caliburn micro 【发布时间】:2021-08-30 14:24:56 【问题描述】:

我尝试通过Entity框架之上的Repositories构建WPF应用程序与数据库交互,我使用caliburn micro作为MVVM框架

问题是当我尝试通过Simple Container 在 ViewModels 中注入 Repertories 时,它不会实例化 My DbContext

存储库

public class UserRepo : IUserRepo

    private AppDb _ctx;

    public UserRepo(AppDb ctx)
    
            _ctx = ctx;
    

应用上下文

public class AppDb : DbContext

    public AppDb(DbContextOptions options) : base(options)
    
    

    public DbSet<User> Users  get; set; 

简单容器上的配置

class Bootstrapper : BootstrapperBase


    private SimpleContainer _container = new SimpleContainer();
    private AppDb _db;
    public Bootstrapper()
    
        Initialize();

        var options = new DbContextOptionsBuilder<AppDb>()
                      .UseSqlServer(@"Server=(localdb)\MSSQLLocalDB;Database=XRaySystem;Integrated Security=True;")
                      .Options;

        _db = new AppDb(options);
    

    protected override void Configure()
    
        _container.Instance(_container);

        _container
            .Singleton<IWindowManager, WindowManager>()
            .Singleton<IEventAggregator, EventAggregator>();
        //register the DataContext
        // i don't know how to add it
        _container.RegisterInstance(typeof(AppDb), null, _db); // <<<<<<<<<< how to add this correctly 
        //Register Reporisotries
        _container
            .PerRequest<IUserRepo, UserRepo>();
        //Register ViewModels
        GetType().Assembly.GetTypes()
            .Where(type => type.IsClass)
            .Where(type => type.Name.EndsWith("ViewModel"))
            .ToList()
            .ForEach(viewModelType => _container.RegisterPerRequest(
                viewModelType, viewModelType.ToString(), viewModelType));
    
    protected override void OnStartup(object sender, StartupEventArgs e)
    


        DisplayRootViewFor<DashBoardViewModel>();
        //base.OnStartup(sender, e);
    

    protected override object GetInstance(Type service, string key)
    
        return _container.GetInstance(service, key);
    

    protected override IEnumerable<object> GetAllInstances(Type service)
    
        return _container.GetAllInstances(service);
    


    protected override void BuildUp(object instance)
    
        _container.BuildUp(instance);
    


查看模型

class DoctorViewModel : Screen

    private readonly IUserRepo _userRepo;

    public DoctorViewModel(IUserRepo userRepo)
    
        _userRepo = userRepo;
    

UserRepo 已实例化,但 AppDb 为空

我的问题

如何配置简单容器将AppDb添加到UserRepo

我转载了同样的problem in on GitHub

【问题讨论】:

你为什么不像以前的电话那样使用_container.Instance(_db); @Nkosi 我之前尝试过...当我使用_container.Instance(_db); 时,同样的问题仍然存在 那么显示的代码应该可以工作,除非提供的示例中省略了更多细节 @Nkosi 我在app on github 中重现了同样的问题,请查看 【参考方案1】:

经过一番调试,我发现Configure方法先运行然后构造函数调用!!所以实例化是在配置已经用 null 完成之后发生的

我通过在 Configure 方法本身中添加 _db 的实例化来解决它

class Bootstrapper : BootstrapperBase


    private SimpleContainer _container = new SimpleContainer();
    private AppDb _db;
    public Bootstrapper()
    
        Initialize();
    

    protected override void Configure()
    
        var options = new DbContextOptionsBuilder<AppDb>()
                     .UseSqlServer(@"Server=(localdb)\MSSQLLocalDB;Database=XRaySystem;Integrated Security=True;")
                     .Options;

        _db = new AppDb(options); //<<<< solve the problem

        _container.Instance(_container);

        _container
            .Singleton<IWindowManager, WindowManager>()
            .Singleton<IEventAggregator, EventAggregator>();
        //register the DataContext
        _container.Instance(_db);
        // _container.RegisterInstance(typeof(AppDb), null, _db); 
        
         //Register Reporisotries
         _container
            .PerRequest<IUserRepo, UserRepo>();
        //Register ViewModels
        GetType().Assembly.GetTypes()
            .Where(type => type.IsClass)
            .Where(type => type.Name.EndsWith("ViewModel"))
            .ToList()
            .ForEach(viewModelType => _container.RegisterPerRequest(
                viewModelType, viewModelType.ToString(), viewModelType));
    
    protected override void OnStartup(object sender, StartupEventArgs e)
    

        DisplayRootViewFor<DashBoardViewModel>();
        //base.OnStartup(sender, e);
    

    protected override object GetInstance(Type service, string key)
    
        return _container.GetInstance(service, key);
    

    protected override IEnumerable<object> GetAllInstances(Type service)
    
        return _container.GetAllInstances(service);
    


    protected override void BuildUp(object instance)
    
        _container.BuildUp(instance);
    


【讨论】:

以上是关于如何使用 caliburn micro 在 Wpf 中注入 EF DbContext的主要内容,如果未能解决你的问题,请参考以下文章

从0到1:使用Caliburn.Micro(WPF和MVVM)开发简单的计算器

Caliburn.Micro-如何从继承的ViewModel在WPF视图中显示多个项目:Conductor 。Collection.AllActive

使用 Caliburn.Micro 4.0.x 和 WPF 的对话框

使用 Caliburn.Micro 的单实例 WPF 应用程序

C#:Caliburn Micro:如何使用数据绑定控制 WPF 按钮的属性?

从Caliburn.Micro,WPF,MVVM中的另一个窗口获取信息