无法将基类(数据契约)强制转换为派生类
本文关键字:转换 派生 契约 基类 数据 | 更新日期: 2023-09-27 18:12:19
[DataContract]
public class SearchCriteria
{
[DataMember]
public string CountryID { get; set; }
}
[DataContract]
public class CitySearchCriteria: SearchCriteria
{
[DataMember]
public string CityID { get; set; }
}
我正在创建一个实例的搜索标准在我的MVC控制器的动作,并试图将其转换为CitySearchCriteria。
SearchCriteria searchCriteria = new SearchCriteria();
searchCriteria.CountryID = "1";
CitySearchCriteria citySearchCriteria = searchCriteria as CitySearchCriteria;
上面语句后面的"citySearchCriteria"对象显示NULL值。我期待它显示两个属性,CountryID和CityID与CountryID填充,和CityID空白…但它将对象设置为NULL。
这里的解决方案是什么?有数据合约做任何与此?
注释提示,不能将基类转换为派生类:但实际上,我已经在我的视图中成功地做到了这一点,它只是在控制器动作中不起作用:
CitySearchCriteria citySearchCriteria = (CitySearchCriteria)Model.SearchCriteria;
这是转换成功,所以为什么不类似的事情在控制器动作工作?
不能这样强制转换!
如果您执行new
,则创建一个特定大小的新内存对象。在您的示例中,new SearchCriteria()
创建了一个新的内存对象,其大小足以容纳一个字符串,不多也不少。
在您的最后一行,您做searchCriteria as CitySearchCriteria
试图将searchCriteria
中的对象转换为更大的类型CitySearchCriteria
。但这是不可能做到的。你正试图"转换"一个内存对象,它持有1个字符串成一个内存对象,可以持有2个字符串。但是强制类型转换并不转换新的内存对象。新字符串的值是多少?它只是检查引用searchCriteria
是否已经包含类型为CitySearchCriteria
的对象。在你的例子中:它没有(对象的类型是SearchCriteria
)并返回null
。
所以…下一个示例可以工作(因为已经创建了CitySearchCriteria)。这也是你的解决方案:
SearchCriteria searchCriteria = new CitySearchCriteria();
CitySearchCriteria citySearchCriteria = searchCriteria as CitySearchCriteria;
和这做不工作(因为CitySearchCriteria尚未创建)。这就是你的情况:
SearchCriteria searchCriteria = new SearchCriteria();
CitySearchCriteria citySearchCriteria = searchCriteria as CitySearchCriteria;
这和下一个例子是一样的。
这个可以工作(因为SearchCriteria已经创建):
object o = new SearchCriteria();
SearchCriteria searchCriteria = o as SearchCriteria;
不(因为SearchCriteria还没有创建)::
object o = new object();
SearchCriteria searchCriteria = o as SearchCriteria;
请注意:我总是使用直接强制转换,而不是使用as
强制转换,除非您想显式地测试对象是否属于该类型。
每个人都已经(正确地)告诉你,你根本不能从Base转换到Derived,但在我看来,你仍然不明白为什么这一行在你的另一段代码中工作:
CitySearchCriteria citySearchCriteria = (CitySearchCriteria)Model.SearchCriteria;
我认为你对实例的"类型"是什么有点困惑。你没有发布模型的定义,但我认为你有这样的东西:
public SearchCriteria SearchCriteria;
这并不意味着SearchCriteria总是包含SearchCriteria的实例,而只是它包含可以转换为SearchCriteria的类型的实例。在您的示例中,它可以包含SearchCriteria或CitySearchCriteria的实例。我想在你的代码中你会发现这样的东西:
Model.SearchCriteria = new CitySearchCriteria();
,这是允许正确执行强制转换的原因。您可以看到实例确实是一个CitySearchCriteria(而不仅仅是SearchCriteria的一个实例),它在强制转换之前执行以下代码:
MessageBox.Show(Model.SearchCriteria.GetType().FullName);
为了更好地理解,您可以尝试在工作强制转换之前修改SearchCriteria中的值,如下所示,结果只会发现强制转换不再工作:
Model.SearchCriteria = new SearchCriteria();
MessageBox.Show(Model.SearchCriteria.GetType().FullName);
CitySearchCriteria citySearchCriteria = (CitySearchCriteria)Model.SearchCriteria;
您可以创建CitySearchCriteria,并将其转换为SearchCriteria。这样您只能看到CountryId。稍后,您可以将其转换回CitySearchCriteria,并查看CountryId和CityId。
这与datcontract无关。在这种情况下,解决方案是创建CitySearchCriteria并将其转换为SearchCriteria(如果需要的话)。