C# 在mvvmcross中的viewmodels之间传递多态类型
我有两个按钮,它们都显示一个新的viewmodel,但传递给viewmodel的数据不同。传递的数据并非完全不同,因此它们都从同一个基继承。不幸的是,传递给viewmodel的Init()方法的数据似乎在途中丢失了其运行时类型信息?使用调试器(或代码),传递的数据仅被识别为基类,而不是实际构造并传递给ShowViewModel()方法的派生类 我想做的是不可能的吗C# 在mvvmcross中的viewmodels之间传递多态类型,c#,android,xamarin,mvvmcross,C#,Android,Xamarin,Mvvmcross,我有两个按钮,它们都显示一个新的viewmodel,但传递给viewmodel的数据不同。传递的数据并非完全不同,因此它们都从同一个基继承。不幸的是,传递给viewmodel的Init()方法的数据似乎在途中丢失了其运行时类型信息?使用调试器(或代码),传递的数据仅被识别为基类,而不是实际构造并传递给ShowViewModel()方法的派生类 我想做的是不可能的吗 public class BasePasser { } public class PasserA : BasePasser {
public class BasePasser
{
}
public class PasserA : BasePasser
{
}
public class PasserB : BasePasser
{
}
public class ViewModelOne : MvxViewModel
{
// ...
private void DoSwitchViewModelA()
{
var tobepassed = new PasserA {
// ...
};
ShowViewModel<ViewModelTwo>(tobepassed);
}
private void DoSwitchViewModelB()
{
var tobepassed = new PasserB {
// ...
};
ShowViewModel<ViewModelTwo>(tobepassed);
}
}
public class ViewModelTwo : MvxViewModel
{
// ...
public async Task Init(BasePasser passed)
{
if(passed is PasserA)
{
// ...
}
else if(passed is PasserB)
{
// ...
}
else
{
// Always called/hit
throw new InvalidOperationException("Unknown data passed");
}
}
}
公共类BasePasser
{
}
公共类通行证A:基本通行证
{
}
公共类通行证B:基本通行证
{
}
公共类ViewModelOne:MvxViewModel
{
// ...
私有void DoSwitchViewModelA()
{
var tobepassed=新的PasserA{
// ...
};
ShowViewModel(待分离);
}
私有void DoSwitchViewModelB()
{
var TOBEPASS=新通行证B{
// ...
};
ShowViewModel(待分离);
}
}
公共类ViewModel2:MvxViewModel
{
// ...
公共异步任务初始化(已传递BasePasser)
{
如果(通过的是PasserA)
{
// ...
}
否则,如果(通过为B)
{
// ...
}
其他的
{
//总是打电话/打电话
抛出新的InvalidOperationException(“传递了未知数据”);
}
}
}
在MvvmCross中显示ViewModel实际上是一个相当复杂的过程
调用ShowViewModel(param)时,Mvx将把param值序列化到名称/值字典中。此时,param的类型信息丢失
当ViewModel被实例化时,它最终将查找ViewModel上定义的任何Init方法
如果查看cirriary.MvvmCross.ViewModels.MvxViewModelExtensions.CallBundleMethod(),您将看到它首先查找具有IMvxBundle类型的单个参数的方法。然后它寻找一个不是简单类型的参数(比如string、int等)
如果找到此类型,则假定它是已在ShowViewModel()调用中序列化的对象。然后,它尝试根据Init方法中参数的类型(而不是原始类型)反序列化该值
这就是为什么您只看到基类型,因为Mvx没有初始调用的类型信息,并且在反序列化时,只看到Init方法中的基类型
解决方法是将所有属性放在一个类中。只设置您需要的,并创建一个鉴别器属性,指定它是哪种“类型”
var param=newpasser{PasserType=“A”,ParamA=“ValueA”,…等}
您还可以选择使用命名方法参数
参见中的Init部分,在MvvmCross中显示ViewModel实际上是一个相当复杂的过程 调用ShowViewModel(param)时,Mvx将把param值序列化到名称/值字典中。此时,param的类型信息丢失 当ViewModel被实例化时,它最终将查找ViewModel上定义的任何Init方法 如果查看cirriary.MvvmCross.ViewModels.MvxViewModelExtensions.CallBundleMethod(),您将看到它首先查找具有IMvxBundle类型的单个参数的方法。然后它寻找一个不是简单类型的参数(比如string、int等) 如果找到此类型,则假定它是已在ShowViewModel()调用中序列化的对象。然后,它尝试根据Init方法中参数的类型(而不是原始类型)反序列化该值 这就是为什么您只看到基类型,因为Mvx没有初始调用的类型信息,并且在反序列化时,只看到Init方法中的基类型 解决方法是将所有属性放在一个类中。只设置您需要的,并创建一个鉴别器属性,指定它是哪种“类型”
var param=newpasser{PasserType=“A”,ParamA=“ValueA”,…等}
您还可以选择使用命名方法参数
请参阅中的Init部分精彩的答案,谢谢您的解释。链接到您所引用的类:可以用Json替换序列化(这是Mvx最初的工作方式)。如果您做到了这一点,并且启用了Json.Net来命名所有类型,那么您应该能够让序列化工作起来。Json序列化的一种方法显示在极好的答案中,感谢您的解释。链接到您所引用的类:可以用Json替换序列化(这是Mvx最初的工作方式)。如果您做到了这一点,并且启用了Json.Net来命名所有类型,那么您应该能够让序列化工作起来。实现Json序列化的一种方法如所示