10
[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 对此有什么作用吗?

评论表明,您不能将基础转换为派生:但实际上,在我看来,我已经成功地做到了这一点,它只是在控制器操作中不起作用:

CitySearchCriteria citySearchCriteria = (CitySearchCriteria)Model.SearchCriteria;

这正在成功转换,那么为什么不在控制器操作中使用类似的东西呢?

4

3 回答 3

13

你不能这样投!

如果你这样做new,你会创建一个特定大小的新内存对象。在您的情况下new SearchCriteria(),创建一个大小足以容纳一个字符串的新内存对象,仅此而已。

在您的最后一行中,您确实searchCriteria as CitySearchCriteria尝试将对象searchCriteria转换为更大的类型CitySearchCriteria。但这是不可能的。您正在尝试将包含 1 个字符串的内存对象“转换”为可以包含 2 个字符串的内存对象。但是强制转换不会转换新的内存对象。新字符串的值是多少?它只是在水下查看以检查您的引用是否searchCriteria已经包含 type 的对象CitySearchCriteria。在您的情况下:它没有(对象是 type 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作为记录:除非您想明确测试对象是否属于该类型,否则我将始终使用直接转换,而不是使用转换。

于 2013-05-06T06:03:58.960 回答
9

每个人都已经(并且正确地)告诉过您,您根本无法从 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;
于 2013-05-06T10:09:28.620 回答
2

您可以创建 CitySearchCriteria,并将其转换为 SearchCriteria。这样你只能看到 CountryId。稍后,您可以将其转换回 CitySearchCriteria,并查看 CountryId 和 CityId。

这与 DataContract 无关。在您的情况下,解决方案是创建 CitySearchCriteria 并将其转换为 SearchCriteria(如果需要)。

于 2013-05-06T06:04:08.030 回答