无法将基类(数据合约)投向派生类。

问题描述 投票:9回答:3
[DataContract]
public class SearchCriteria
{
    [DataMember]
    public string CountryID { get; set; }    
}

[DataContract]
public class CitySearchCriteria: SearchCriteria
{
    [DataMember]
    public string CityID { get; set; }
}

我在我的MVC控制器动作中创建了一个SearchCriteria的实例,并试图将其转换为CitySearchCriteria。

SearchCriteria searchCriteria = new SearchCriteria();
searchCriteria.CountryID = "1";
CitySearchCriteria citySearchCriteria = searchCriteria as CitySearchCriteria;

在上述语句之后,"citySearchCriteria "对象显示的是NULL值。我希望它能同时显示两个属性,CountryID和CityID,其中CountryID被填充,CityID为空白......但它却将对象设置为NULL。

这里的解决方案是什么?有DataContract来解决这个问题吗?

评论中建议,你不能将base转换为derive:,但实际上,我已经在我的视图中成功地完成了这一操作,只是在controller action中无法使用。

CitySearchCriteria citySearchCriteria = (CitySearchCriteria)Model.SearchCriteria;

这个转换成功了 为什么在控制器操作中不能成功呢?

c# oop casting datacontract derived-class
3个回答
8
投票

每个人都已经(而且是正确的)告诉了你,你根本不能从Base到Derived的转换,但是在我看来,你似乎仍然没有明白为什么这一行在你的另一章代码中可以工作。

CitySearchCriteria citySearchCriteria = (CitySearchCriteria)Model.SearchCriteria;

我认为你对一个实例的 "类型 "是什么有点困惑。你没有发布Model的定义,但我认为你有这样的东西。

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;

11
投票

你不能这样投射!

如果你这样做 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除非你想显式地测试一个对象是否属于该类型。


2
投票

你可以创建CitySearchCriteria,并将其转换为SearchCriteria。这样你就只能看到CountryId。之后,你可以把它转回CitySearchCriteria,并看到CountryId和CityId。

这与DataContract无关。在你的情况下,解决方案是创建CitySearchCriteria,然后把它转为SearchCriteria(如果你需要的话)。

© www.soinside.com 2019 - 2024. All rights reserved.