我需要了解的是它如何在移动应用程序世界中运行,尤其是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;
}
最后,我不确定这是否是一个优雅的解决方案,但它的工作原理.
