【问题标题】:By-request singleton initialization using IoC container in MVVM application在 MVVM 应用程序中使用 IoC 容器按请求进行单例初始化
【发布时间】:2015-04-20 18:37:10
【问题描述】:

我的 WPF 应用程序使用 Caliburn.Micro 作为 MVVM 框架,使用实体框架作为数据访问技术。应用程序的目的是维护数据库。有多个Views 由菜单和结果数据网格组成。使用菜单控件,用户指定必须在结果数据网格中显示哪些 DB 数据。不同Views 中的一些ComboBoxes 在其ViewModels 中绑定到相同的属性List<EntityName>。(菜单有相同的项目可供选择)。当 ViewModel 初始化时,每个列表都从 DB 加载。我不想从数据库中为每个视图加载相同的列表,我想制作一次。为了实现这一点,我已经将这个List 属性移动到另一个类MenuLists 并使用PreloadLists() 方法从数据库中获取一次列表,然后使用Caliburn 的内置IoC 容器将这个类作为单例注入每个ViewModel。像这样:

IoC 容器配置:

container.PerRequest<KitchenOneViewModel>();
container.PerRequest<KitchenTwoViewModel>();
container.Singleton<IMenuLists, MenuLists>();

MenuLists类:

public class MenuLists : IMenuLists
{

    public List<Meat> MeatLst { get; set; }
    public List<Fish> FishLst { get; set; }

    public void PreloadLists()
    {
        using (var db = new DBEntities())
        {
            MeatLst = db.Meat.OrderBy(x => x.MeatName).ToList();
            FishLst = db.Fish.OrderBy(x => x.FishName).ToList();
        }
    }
}

在 ViewModel 中注入:

public KitchenOneViewModel(IMenuLists menuLists)
    {
        _menuLists = menuLists;
    }

问题是我需要以某种方式调用MenuLists.PreloadLists(),但如果我在MenuLists 构造函数中执行此操作,我将在第一个ViewModel 初始化中获得长时间的UI 冻结,因为MenuLists 的构造函数(具有昂贵的PreloadLists() DB-access 操作)将被调用。我不知道Views 会先打开什么,所以我不能从那里调用PreloadLists 方法。我需要在不冻结 UI 的情况下预加载我的列表一次。我该如何解决?也许会以某种方式延迟MenuLists 初始化?

【问题讨论】:

  • 列表永远不会改变吗?也许在“PreloadLists”函数中添加一个“已加载”标志,并检查该标志,如果其为真,则返回,如果不加载列表。然后,您可以在应用程序启动时在另一个线程中调用该函数,或者作为闪屏操作的一部分(如果它已经加载,您也可以在每个函数中调用它而几乎没有影响)。你也可以有一个“ResetLists”函数来重置加载的标志并在列表发生变化时重新加载......

标签: c# mvvm dependency-injection singleton lazy-initialization


【解决方案1】:

要么懒惰地单独加载每个列表以减少初始化时间,例如:

//only initialized when it's used
private static Lazy<List<Meat>> meatList 
     = new Lazy<List<Meat>>(
             () =>
             {
                 //load single list here
             }
     );
public List<Meat> MeatList { get{ return meanList.Value; } }

...或者如果您想一次初始化所有内容,请在您的应用程序启动时这样做,而不是等待 ViewModel 被实例化。

或者,如果您不需要阻止,您可以考虑将初始化设置为 async

【讨论】:

  • Lazy 正是我想要的。谢谢!
猜你喜欢
  • 1970-01-01
  • 2023-04-07
  • 2020-12-13
  • 1970-01-01
  • 2017-12-09
  • 2011-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多