使用 MEF 的模板 10 依赖注入

Template 10 dependency injection using MEF

我熟悉在 .NET Framework 4.6.* 中使用 MEF,但不熟悉在 .NET Core 中的使用。我正在研究模板 10 中的 Hamburger 模板,看看它是否适合我的需要,但我一直无法弄清楚如何使用 MEF 来组成我的视图模型。

我的问题是如何使用导航服务以 MEF 注入其视图模型的方式导航到视图?

我有一种方法可以让它工作,但它似乎有点代码臭味,所以欢迎更好的答案。我创建了一个包含 CompositionHost 实例的静态 class。它有一个解析导入的方法。视图后面的代码调用静态 class 来创建其视图模型。

public static class Container
{
    public static CompositionHost Host { get; set; }

    public static T Get<T>()
    {
        T obj = Host.GetExport<T>();
        Host.SatisfyImports(obj);
        return obj;
    }
}

App class:

public override async Task OnStartAsync(StartKind startKind, IActivatedEventArgs args)
    {
        var config = new ContainerConfiguration();
        Container.Host = config.WithAssembly(GetType().GetTypeInfo().Assembly).CreateContainer();

        await NavigationService.NavigateAsync(typeof(Views.MainPage));
    }

在视图后面的代码中:

public sealed partial class MainPage : Page
{
    private MainPageViewModel ViewModel { get; }

    public MainPage()
    {
        InitializeComponent();
        NavigationCacheMode = Windows.UI.Xaml.Navigation.NavigationCacheMode.Enabled;
        ViewModel = Container.Get<MainPageViewModel>();
        DataContext = ViewModel;
    }
}

糟糕,我没发现这个:

How do I use a Unity IoC container with Template10?

最后,我找到了这样的解决方案:

public interface IView
{
    ViewModelBase ViewModel { get; }
}

[Export]
public sealed partial class MainPage : Page, IView
{
    public ViewModelBase ViewModel
    {
        get
        {
            return VM as ViewModelBase;
        }
    }

    [Import]
    public MainPageViewModel VM { get; set; }

    public MainPage()
    {
        InitializeComponent();
        NavigationCacheMode = Windows.UI.Xaml.Navigation.NavigationCacheMode.Enabled;
    }
}

并且在 App.xaml.cs 中:

public override async Task OnStartAsync(StartKind startKind, IActivatedEventArgs args)
    {
        var config = new ContainerConfiguration();
        _container = config.WithAssembly(GetType().GetTypeInfo().Assembly).CreateContainer();
        await NavigationService.NavigateAsync(typeof(Views.MainPage));
    }       

    public override INavigable ResolveForPage(Page page, NavigationService navigationService)
    {
        _container.SatisfyImports(page);
        return (page as IView)?.ViewModel;
    }