c# - 无法在 2 个程序集(UWP、Splat)之间注册 View 和 ViewModel

标签 c# reactiveui splat .net-standard-2.0

使用最新的 RxUI v8 预览版和 Splat 2.0,在引用 .Net Standard 2.0 库的 UWP 项目中,我无法注册 View 和 View 模型,除非它们驻留在同一程序集中。

我有:

Locator.CurrentMutable.RegisterLazySingleton(() => new HomeView(), typeof(IViewFor<HomeViewModel>));

但是 Splat 给出了错误:

DefaultViewLocator: Failed to find type named 'RxUI.UWP.Core.Views.HomeView, RxUI.UWP.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
DefaultViewLocator: Failed to resolve service for type 'ReactiveUI.IViewFor`1[[RxUI.UWP.Core.ViewModels.HomeViewModel, RxUI.UWP.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]'.
DefaultViewLocator: Failed to find type named 'ReactiveUI.IRoutableView, ReactiveUI, Version=8.0.0.0, Culture=neutral, PublicKeyToken=null'.
DefaultViewLocator: Failed to resolve service for type 'ReactiveUI.IViewFor`1[[ReactiveUI.IRoutableViewModel, ReactiveUI, Version=8.0.0.0, Culture=neutral, PublicKeyToken=null]]'.
DefaultViewLocator: Failed to resolve view for view model type 'ReactiveUI.IRoutableViewModel'.
DefaultViewLocator: Failed to find type named 'RxUI.UWP.Core.Views.HomeView, RxUI.UWP.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.

因此它正在“Core”程序集中查找 HomeView,但它驻留在 UWP 项目中。这是结构...

enter image description here

最佳答案

我在与您类似的环境中遇到了同样的问题。 The issue resided in the DefaultViewLocator ,因为 View 类型被重命名并错误地解析为 View 模型的程序集和命名空间。 有关如何确定 View 类型名称的信息,请参阅第 133-134 行:

var viewModelTypeName = viewModelType.AssemblyQualifiedName;
var proposedViewTypeName = this.ViewModelToViewFunc(viewModelTypeName);

注意:ViewModelToViewFunc 只是一个 String.Replace,它将“ViewModel”替换为“View”(请参阅​​构造函数)。

为了解决这个问题,我的解决方法是创建我自己的 IViewLocator 实现,例如:

public class MyViewLocator : IViewLocator {
   public MyViewModelLocator(Assembly viewAssembly, string viewNameSpace)
...
   private IViewFor AttemptViewResolutionFor(Type viewModelType, string contract)
    {
        // proposed view type is now based on provided namespace + classname as modified by ViewModelToViewFunc
        if (viewModelType == null) return null;
        var viewModelTypeName = viewModelType.Name;
        var proposedViewTypeName = _viewNamespace + "." +  this.ViewModelToViewFunc(viewModelTypeName);
...

   private IViewFor AttemptViewResolution(string viewTypeName, string contract)
    {
        try
        {
            // resolve view type in the assembly of the view, and not assembly of the viewmodel
            var viewType = _viewAssembly.GetType(viewTypeName); // instead of Reflection.ReallyFindType(viewTypeName, throwOnFailure: false);
...
}

最后,您的自定义 View 定位器实现必须使用 splat 注册,以便它覆盖 DefaultViewLocator 实现:

Locator.CurrentMutable.RegisterConstant<IViewLocator>(new MyViewLocator(typeof(SplashView).Namespace, typeof(SplashView).Assembly));

关于c# - 无法在 2 个程序集(UWP、Splat)之间注册 View 和 ViewModel,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47755145/

相关文章:

ruby - Ruby 中使用的独立 splat 运算符 (*) 是什么?

c# - 反序列化真实世界的 JSON 数据

c# - 方法:什么是更好的列表或对象?

wpf - 如何使用 ReactiveUI 实现倒数计时器?

c# - 有没有一种方法可以使用 Reactive UI 订阅所有分层属性更改?

arrays - 啪啪的解释

ruby - *::(星号双冒号)在 Ruby 中做什么?

c# - 将非常大的数据集写入文本文件

c# - 以编程方式检查 Gac 中是否存在 dll。如果存在,则将其显示在网格中

c# - 我应该如何过滤绑定(bind)到网格的 IReactiveList?