通过 Bootstrapper OnStartUp 将 Repository 注入 ShellViewModel

Injection of Repository into ShellViewModel, via Bootstrapper OnStartUp

我卡住了!

我正在使用 Caliburn.micro 来消除在 WPF 应用程序中实施 MVVM 的一些痛苦。

目前我只有一个 View / ViewModel,但将来可能会有多个 ViewModel。当前的 ViewModel 正在使用存储库来填充对象列表:

public class ShellViewModel : Screen
{

    private IMyObjectRepository<IMyObject> _myObjectsRepo = null;
    private BindableCollection<MyObject> _myObjects;
    private string _connString;


    /// <summary>
    /// constructor
    /// </summary>
    public ShellViewModel()
    {
        //call the method which sets up the repository
        GetMyObjectsRepository();

        //following three lines cast the list from type IReport to type Report
        var IMyObjects= _myObjectsRepo.GetAllIMyObjects();
        var myObjects = IMyObjects.OfType<MyObject>().ToList();
        MyObjects = new BindableCollection<MyObject>(myObjects );
    }

    private void GetMyObjectsRepository()
    {
        _connString = ConfigurationManager.ConnectionStrings["xxx"].ConnectionString;
        _myObjectRepo = MyObjectRepositoryFactory.InstantiateRepo(_connString);
    }

上面的问题听起来像是一个未来的问题——如果我创建一个不同的 ViewModel,它有自己的 BindableCollection<MyObject> _myObjects; 属性,那么相同对象的两个集合可能很快就会有不同的状态,即第一个是 ObjectX ViewModel 可能会更改其名称属性,但 ObjectX 在第二个 ViewModel 中仍具有其原始名称。

我想我可以在构建时将这个 <MyObject> 列表注入到 ViewModel 中 - 我应该在 Bootstrapper.cs 中这样做吗? (我宁愿避免完全成熟的 DI,因为这是一个小项目)

目前 Bootstrapper.cs 如下所示 - 如何将上述代码片段中的一些逻辑移至此处?它是否进入 OnStartUp 事件方法?如果是那么怎么办?

using Caliburn.Micro;
using Prototype_WPF.ViewModels;
using System.Windows;

namespace Prototype_WPF
{
    public class Bootstrapper: BootstrapperBase
    {

        public Bootstrapper()
        {
            Initialize();
        }

        protected override void OnStartup(object sender, StartupEventArgs e)
        {
            DisplayRootViewFor<ShellViewModel>();
        }

    }
}

您可以创建一个单独的组件来检索您的对象,例如 IMyObjectService 并实现它。

public interface IMyObjectService
{
     IList<MyObject> GetMyObjects();
}

然后在 Bootstrapper 中创建 Configure 方法的重载并注册一个实现,类似于:

protected override void Configure()
{
      container = new SimpleContainer();

      container.Singleton<IMyObjectService, MyObjectService>();
      //other registrations
      container.PerRequest<ShellViewModel>();
}

最后使用任何 ViewModel 的构造函数注入来注入和使用此服务。 Caliburn.Micro 文档已经有一些 examples

您可以使用 Handler 方法在引导程序中为您的视图模型注册工厂方法:

public class Bootstrapper : BootstrapperBase
{
    private readonly BindableCollection<MyObject> _myObjects = new BindableCollection<MyObject>();
    private SimpleContainer container;

    public Bootstrapper()
    {
        Initialize();
    }

    protected override void Configure()
    {
        container = new SimpleContainer();
        container.Singleton<IWindowManager, WindowManager>();
        container.Handler<ShellViewModel>(_ => new ShellViewModel(_myObjects));
        container.Handler<SomeOtherViewModel>(_ => new SomeOtherViewModel(_myObjects));
    }

    protected override void OnStartup(object sender, StartupEventArgs e)
    {
        DisplayRootViewFor(typeof(ShellViewModel));
    }

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

您可以 'Register' 服务和 'Register' 每 class 如下

protected override void Configure()
    {
        container = new SimpleContainer();

        container.Instance(container);

        container
            .Singleton<IMyObjectService, MyObjectService>();

        //Register all ViewModel classes            
        GetType().Assembly.GetTypes()
            .Where(type => type.IsClass)
            .Where(type => type.Name.EndsWith("ViewModel"))
            .ToList()
            .ForEach(viewModleType => container.RegisterPerRequest(
                viewModleType, viewModleType.ToString(), viewModleType));

    }