【问题标题】:Cannot cast from Base to Derived无法从基础转换为派生
【发布时间】:2018-03-01 14:44:24
【问题描述】:

我有一个 Employee 类,以及从它派生的 FulltimeEmployee 和 ParttimeEmployee 类。我在 Employee 类上应用了一个 [KnownType] 属性。 Employee 类用作 WCF 服务的 DataContract。

我有一个 MVC 应用程序作为 WCF 客户端。我根据需要成功检索了 FulltimeEmployee 或 ParttimeEmployee,并将其用作视图的模型。该模型是基本类型 Employee。层次结构被保留:

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "0.5.0.0")]
[System.Runtime.Serialization.DataContractAttribute(Name="FullTimeEmployee", Namespace="http://schemas.datacontract.org/2004/07/EmployeeService")]
public partial class FullTimeEmployee : EmployeeService.Employee
{
    ...

但是当我尝试保存一个新员工时,我得到了一个异常:

InvalidCastException:无法转换类型的对象 'EmployeeService.Employee' 输入'EmployeeService.PartTimeEmployee'。

代码如下:

Employee emp = null;
if(employee.Type == EmployeeType.FullTimeEmployee)
{
     ...
}
else
{
           emp = new PartTimeEmployee
            {
                Name = employee.Name,
                Gender = employee.Gender,
                Type = employee.Type,
                DateOfBirth = employee.DateOfBirth,
                HourlyPay = ((PartTimeEmployee)employee).HourlyPay,
                HoursWorked = ((PartTimeEmployee)employee).HoursWorked
            };

为什么会这样?

【问题讨论】:

  • “当我尝试保存新员工时”,我没有看到任何与保存相关的内容。它到底在哪里失败了?
  • 通常当使用这种结构时(检查 type == x 等)表明设计不好
  • 这里没有关于类及其层次结构的足够信息,而且您提到的实际演员表代码甚至都不存在。如果Employee 不是一个抽象类,并且你有一个这种类型的实际实例化对象,那么显然你不能将它转换为子类型。因为不是。
  • 您说MVC中的视图模型是基本类型Employee。这意味着视图会将Employee 的实例提交回控制器。那时您没有任何关于 Employee 子类型的信息,因此无法将其转换为子类型。这是基本的 OOP 基础。
  • 使用这种方法基本上会丢失子类型的属性。因此,您需要为每个子类型作为模型有不同的视图和发布操作。

标签: c# wcf


【解决方案1】:

我不会详细介绍,因为在 cmets 中已经提到这是一个糟糕的设计,并且由于您提到您正在学习教程,所以我不会对您施加压力。

一个快速而肮脏的解决方法是加载所有属性,而不考虑类型:

public class BadPractice
{
    ... full time properties
    ... part time properties
}

然后,加载它:

var badPractice = new BadPractice();

if (...)
{
    badPractice.PartTimeProperty = ...;
}
else
{
    badPractice.FullTimeProperty = ...;
}

return View(badPractice);

并确保将其返回到Controller

public ActionResult HorriblyBad(BadPractice badPractice)
{
    if (badPractice.Type == EmployeeType.FullTime)
    {
        ...
    }
}

请注意由于糟糕的设计而必须做的所有工作。我不会继续看那些教程。

【讨论】:

  • 感谢您的回答。它实际上是一个很好的 WCF 教程。作为奖励,我可以问一下在这种情况下您会建议什么设计?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-19
  • 2019-07-10
相关资源
最近更新 更多