我需要了解的是它如何在移动应用程序世界中运行,尤其是UWP Template 10 Mobile应用程序.
从我的过去,在.net / Asp应用程序中我可以“RegisterType(new XYZ).Singleton()blah”{请原谅语法;只是一个例子}在App_Start.ConfigureServices中.这在.netcore中几乎完全相同,授予了一些语法更改.
我的问题是现在我正在尝试提供我的api将要使用的UWP应用程序需要消化我的IXYZ服务.我绝不认为他们每次都应该“新”一个实例.必须有一种方法将其注入UWP方面的容器中;而且我觉得我在这个过程中遗漏了一些非常简单的东西.
这是我的代码:
App.xaml.cs
public override async Task OnStartAsync(StartKind startKind, IActivatedEventArgs args) { // TODO: add your long-running task here //if (args.Kind == ActivationKind.LockScreen) //{ //} RegisterServices(); await NavigationService.NavigateAsync(typeof(Views.SearchCompanyPage)); } public static IServiceProvider Container { get; private set; } private static void RegisterServices() { var services = new ServiceCollection(); services.AddSingleton<IXYZ, XYZ>(); Container = services.BuildServiceProvider(); }
MainPage.xaml.cs中:
public MainPage() { InitializeComponent(); NavigationCacheMode = NavigationCacheMode.Enabled; }
MainPageViewModel:
public class MainPageViewModel : ViewModelBase { private readonly IXYZ _xyz; public MainPageViewModel(IXYZ xyz) { //Stuff _xyz= xyz; } }
我现在得到错误:
XAML MainPage …无法构造ViewModel类型.为了在XAML中构造,类型不能是抽象的,接口嵌套的泛型或结构,并且必须具有公共默认构造函数.
我愿意使用任何品牌的IoC Container,但我需要的是如何在UWP应用中正确使用DI服务的示例.关于DI的99.9%的问题是关于视图(即Prism?)而不仅仅是服务的简单DI(即DataRepo;又称API / DataService).
再一次,我觉得我错过了一些明显的东西,需要在正确的方向上轻推.有人可以向我展示一个示例项目,基本代码,或基于我不应该成为程序员的基础……请不要这样做(我不知道我的自我是否可以接受它).
在@mvermef和SO问题 Dependency Injection using Template 10的帮助下,我找到了解决方案.事实证明这是一个兔子洞,每次转弯都会遇到问题.第一个问题是让依赖注入工作.一旦我能够从上面的来源中弄明白,我就可以开始将我的服务注入ViewModels并将它们设置为后面代码中的DataContext.
然后我遇到注入问题,将我的IXYZ服务注入到UserControls的ViewModels中.
Pages和他们的ViewModel工作得很好,但我遇到的问题是UserControl的DataContext没有注入UserControl的ViewModel.相反,它们是由持有它的Page的ViewModel注入的.
最终的解决方案是确保UserControl在XAML中设置DataContext而不是后面的代码,就像我们对Pages一样,然后在后面的代码中创建DependencyProperty.
要显示下面的基本解决方案.
为了使它工作,我开始:
APP.XAML.CS
public override async Task OnStartAsync(StartKind startKind, IActivatedEventArgs args) { // long-running startup tasks go here RegisterServices(); await Task.CompletedTask; } private static void RegisterServices() { var services = new ServiceCollection(); services.AddSingleton<IRepository, Repository>(); services.AddSingleton<IBinderService, BinderServices>(); **//ViewModels** **////User Controls** services.AddSingleton<AddressesControlViewModel, AddressesControlViewModel>(); services.AddSingleton<CompanyControlViewModel, CompanyControlViewModel>(); **//ViewModels** **////Pages** services.AddSingleton<CallListPageViewModel, CallListPageViewModel>(); services.AddSingleton<CallListResultPageViewModel, CallListResultPageViewModel>(); etc.... Container = services.BuildServiceProvider(); } public override INavigable ResolveForPage(Page page, NavigationService navigationService) { **//INJECT THE VIEWMODEL FOR EACH PAGE** **//ONLY THE PAGE NOT USERCONTROL** if (page is CallListPage) { return Container.GetService<CallListPageViewModel>(); } if (page is CallListResultPage) { return Container.GetService<CallListResultPageViewModel>(); } etc... return base.ResolveForPage(page, navigationService); }
在页面背后的代码中
CALLLISTPAGE.XAML.CS
public CallListPage() { InitializeComponent(); } CallListPageViewModel _viewModel; public CallListPageViewModel ViewModel { get { return _viewModel ?? (_viewModel = (CallListPageViewModel)DataContext); } }
在您的XAML中添加您的UserControl
CALLLISTPAGE.XAML
< binder:CompanyControl Company =“{x:Bind ViewModel.SelectedCompany,Mode = TwoWay}”/>
在您的UserControl中,确保将DataContext添加到XAML而不是像我们对页面那样添加代码.
COMPANYCONTROL.XAML
<UserControl.DataContext> <viewModels:CompanyControlViewModel x:Name="ViewModel" /> </UserControl.DataContext>
在UserControl代码后面添加一个依赖属性
COMPANYCONTROL.XAML.CS
public static readonly DependencyProperty CompanyProperty = DependencyProperty.Register( "Company", typeof(Company), typeof(CompanyControl), new PropertyMetadata(default(Company), SetCompany)); public CompanyControl() { InitializeComponent(); } public Company Company { get => (Company) GetValue(CompanyProperty); set => SetValue(CompanyProperty, value); } private static void SetCompany(DependencyObject d, DependencyPropertyChangedEventArgs e) { var control = d as CompanyControl; var viewModel = control?.ViewModel; if (viewModel != null) viewModel.Company = (Company) e.NewValue; }
最后,我不确定这是否是一个优雅的解决方案,但它的工作原理.