【问题标题】:How do I use a Unity IoC container with Template10?如何将 Unity IoC 容器与 Template10 一起使用?
【发布时间】:2016-09-23 23:07:26
【问题描述】:

我有一个基于 Template10 的应用程序,并希望使用 IoC 处理我的依赖注入。我倾向于为此使用 Unity。我的应用分为三个程序集:

  1. UI(通用应用)
  2. UI 逻辑(通用库)
  3. 核心逻辑(便携式库)。

我有这些问题:

  1. 我应该为整个应用使用一个容器,还是为每个程序集创建一个?
  2. 我应该在哪里创建容器并注册我的服务?
  3. 不同程序集中的不同类应如何访问容器?单例模式?

我已经阅读了很多关于 DI 和 IoC 的内容,但我需要知道如何在实践中应用所有理论,特别是在 Template10 中。

注册码:

// where should I put this code?
var container = new UnityContainer();
container.RegisterType<ISettingsService, RoamingSettingsService);

然后是检索实例的代码:

var container = ???
var settings = container.Resolve<ISettingsService>();

【问题讨论】:

标签: c# .net unity-container uwp template10


【解决方案1】:

我不熟悉Unity Container

我的示例是使用LightInject,您可以使用Unity 应用类似的概念。 要在 ViewModel 上启用 DI,您需要在项目中覆盖 App.xaml.cs 上的 ResolveForPage

public class MainPageViewModel : ViewModelBase
{
    ISettingsService _setting;
    public MainPageViewModel(ISettingsService setting)
    {
       _setting = setting;
    }
 }


[Bindable]
sealed partial class App : Template10.Common.BootStrapper
{
    internal static ServiceContainer Container;

    public App()
    {
        InitializeComponent();
    }

    public override async Task OnInitializeAsync(IActivatedEventArgs args)
    {
        if(Container == null)
            Container = new ServiceContainer();

        Container.Register<INavigable, MainPageViewModel>(typeof(MainPage).FullName);
        Container.Register<ISettingsService, RoamingSettingsService>();

        // other initialization code here

        await Task.CompletedTask;
    }

    public override INavigable ResolveForPage(Page page, NavigationService navigationService)
    {
        return Container.GetInstance<INavigable>(page.GetType().FullName);
    }
}

如果您想在MainPage.xaml.cs 上使用{x:bind}Template10 将自动将DataContext 设置为MainPageViewModel

public class MainPage : Page
{
    MainPageViewModel _viewModel;

    public MainPageViewModel ViewModel
    {
      get { return _viewModel??(_viewModel = (MainPageViewModel)this.DataContext); }
    }
}

【讨论】:

  • 感谢您的回答!这对我来说效果很好!有没有办法将 VM 注入 Shell 视图?
  • @NickGoloborodko 我不太了解您的问题,也许您应该为此创建新的 SO 问题?
【解决方案2】:

这是我如何使用 Unity 和 Template 10 的一个小例子。

1.创建视图模型

我还创建了一个 DataService 类来创建人员列表。 看看 [Dependency] 注释。

public class UnityViewModel : ViewModelBase
{
    public string HelloMessage { get; }

    [Dependency]
    public IDataService DataService { get; set; }

    private IEnumerable<Person> people;
    public IEnumerable<Person> People
    {
        get { return people; }
        set { this.Set(ref people, value); }
    }

    public UnityViewModel()
    {
        HelloMessage = "Hello !";
    }

    public override async Task OnNavigatedToAsync(object parameter, NavigationMode mode,
        IDictionary<string, object> suspensionState)
    {
        await Task.CompletedTask;
        People = DataService.GetPeople();
    }
}

2。创建一个类来创建和填充你的 UnityContainer

将 UnityViewModel 和 DataService 添加到 unityContainer。 创建一个属性来解析 UnityViewModel。

public class UnitiyLocator
{
    private static readonly UnityContainer unityContainer;

    static UnitiyLocator()
    {
        unityContainer = new UnityContainer();
        unityContainer.RegisterType<UnityViewModel>();
        unityContainer.RegisterType<IDataService, RuntimeDataService>();
    }

    public UnityViewModel UnityViewModel => unityContainer.Resolve<UnityViewModel>();
}

3.将 UnityLocator 添加到您的 app.xaml

<common:BootStrapper x:Class="Template10UWP.App"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:common="using:Template10.Common"
                 xmlns:mvvmLightIoc="using:Template10UWP.Examples.MvvmLightIoc"
                 xmlns:unity="using:Template10UWP.Examples.Unity">


<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="Styles\Custom.xaml" />
            <ResourceDictionary>
                <unity:UnitiyLocator x:Key="UnityLocator"  />
            </ResourceDictionary>
        </ResourceDictionary.MergedDictionaries>

        <!--  custom resources go here  -->

    </ResourceDictionary>
</Application.Resources>

4.创建页面

使用 UnityLocator 将 UnityViewModel 设置为 DataContext 并将属性绑定到控件

<Page
x:Class="Template10UWP.Examples.Unity.UnityMainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Template10UWP.Examples.Unity"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
DataContext="{Binding Source={StaticResource UnityLocator}, Path=UnityViewModel}"
mc:Ignorable="d">

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <TextBlock Text="{Binding HelloMessage}" HorizontalAlignment="Center"
               VerticalAlignment="Center" />

    <ListBox Grid.Row="1" ItemsSource="{Binding People}" DisplayMemberPath="FullName">

    </ListBox>
</Grid>

页面解析UnityViewModel时会自动注入DataService。

现在回答您的问题

  1. 这取决于项目如何相互依赖。我不确定什么是最好的解决方案,但我想我会尝试使用一个 UnityContainer 并将其放在核心库中。

  2. 我希望我的例子回答了这个问题

  3. 我希望我的例子回答了这个问题

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-23
    • 2023-03-20
    • 1970-01-01
    相关资源
    最近更新 更多