简体   繁体   English

如何将Unity IoC容器与Template10一起使用?

[英]How do I use a Unity IoC container with Template10?

I have an app based on Template10 and want to handle my dependency injection using IoC. 我有一个基于Template10的应用程序,想使用IoC处理依赖项注入。 I am leaning toward using Unity for this. 我倾向于为此使用Unity。 My app is divided into three assemblies: 我的应用程序分为三个程序集:

  1. UI (Universal app) UI(通用应用)
  2. UI Logic (Universal Library) UI逻辑(通用库)
  3. Core Logic (Portable Library). 核心逻辑(便携式库)。

I have these questions: 我有以下问题:

  1. Should I use a single container for the whole app, or create one for each assembly? 我应该为整个应用程序使用一个容器,还是为每个程序集创建一个容器?
  2. Where should I create the container(s) and register my services? 我应该在哪里创建容器并注册我的服务?
  3. How should different classes in the various assemblies access the container(s)? 各种程序集中的不同类应如何访问容器? Singleton pattern? 单例模式?

I have read a lot about DI and IoC but I need to know how to apply all the theory in practice, specifically in Template10. 我已经阅读了很多有关DI和IoC的文章,但是我需要知道如何在实践中应用所有理论,尤其是在Template10中。

The code to register: 要注册的代码:

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

And then the code to retrieve the instances: 然后获取实例的代码:

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

I not familiar with Unity Container . 我对Unity Container不熟悉。

My example is using LightInject , you can apply similar concept using Unity . 我的示例使用的是LightInject ,您可以使用Unity应用类似的概念。 To enable DI on ViewModel you need to override ResolveForPage on App.xaml.cs on your project. 要在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);
    }
}

Template10 will automaticaly set DataContext to MainPageViewModel , if you want to use {x:bind} on MainPage.xaml.cs : Template10机器会自动设置DataContextMainPageViewModel ,如果你想使用{x:bind}MainPage.xaml.cs

public class MainPage : Page
{
    MainPageViewModel _viewModel;

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

here is a small example how i use Unity and Template 10. 这是一个小示例,说明我如何使用Unity和Template 10。

1. Create a ViewModel 1.创建一个ViewModel

I also created a DataService class to create a list of people. 我还创建了一个DataService类来创建人员列表。 Take a look at the [Dependency] annotation. 看一下[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. Create a Class to create and fill your UnityContainer 2.创建一个类以创建并填充您的UnityContainer

Add the UnityViewModel and the DataService to the unityContainer. 将UnityViewModel和DataService添加到unityContainer。 Create a property to resolve the UnityViewModel. 创建一个属性以解析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. Add the UnityLocator to your app.xaml 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. Create the page 4.创建页面

Use the UnityLocator to set the UnityViewModel as DataContext and bind the properties to the controls 使用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>

The DataService will be injected automatically when the page resolves the UnityViewModel. 页面解析UnityViewModel时,将自动注入DataService。

Now to your questions 现在您的问题

  1. This depends on how the projects depend on each other. 这取决于项目之间如何相互依赖。 I am not sure what´s the best solution, but i think i would try to use one UnityContainer and place it in the core library. 我不确定什么是最佳解决方案,但是我想我会尝试使用一个UnityContainer并将其放置在核心库中。

  2. I hope my examples answered this question 我希望我的例子能回答这个问题

  3. I hope my examples answered this question 我希望我的例子能回答这个问题

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM