InvalidCastException虽然上传无编译错误

问题描述:

我基本上试图做的是将从Web服务获得的对象转换为与我的实体框架对象兼容的对象。我虽然通过创建一个接口,这两个应用于EF对象的Web服务对象&这样做。这样我就可以轻松地从一种类型投射到另一种类型。 在这一点上,我有以下对象:A,A1,B和接口IAB。InvalidCastException虽然上传无编译错误

我没有面临的问题是当我从对象A向A1进行upcast时出现运行时错误但没有编译错误。我想知道为什么我的upcast不被接受?

public class A 
{ 
    //Has variables & Properties 
} 

public class A1 : A, IAB 
{ 
    //Has some properties 
} 

注:我需要创建A1作为扩展Web服务的部分A级创建序列化的问题。所以这似乎是最好的解决方案。

在联系服务时,我要求提供一个A对象列表,然后将它们上传到A1。后来,我将它们转换成B.

我试着投的对象是这样的:

List<A1> allA1 = new List<A1>(); 
foreach (A item in retrievedListOfA) 
{  
    allA1.Add((A1)item); 
} 

由于我没有得到任何编译错误,我觉得很奇怪,我得到这个错误。如果我对“A是A1”类型进行检查,那么它永远不会进入if语句。

有人可以指出为什么这会产生问题吗?是否因为对象A来自Web服务?

注意:如果这种“移植”对象从一个到另一个的方法是完全荒谬的,请给我一些指示应该如何完成。这是我第一次尝试这样的事情。

+0

就个人而言,我不会直接使用来自webservice的对象。我会考虑为“A”创建一个本地实体(比如localA)。也从一个来自webservice的对象继承是一个坏主意。 – Krishna

+0

检查什么是异常时'项目'的类型 –

你没有得到任何编译错误,因为(A1)项,你是在对编译器说,我知道我在做什么,所以闭嘴。

因此,如果retrieveListOfA是一个As和A1s的集合,那么每个您投入到A1的A,实际上是一个A然后调用一个A1方法就会爆炸。

有很多移植方法,例如,一个转换器,铸造不是其中之一。

+0

铸件确实不是一种方法,谢谢你的建议!我看了一下Converter,它工作得很好。你确实需要自己映射属性(在委托方法中),但这对我的解决方案没有任何问题。 对于对象较大的人可能会觉得这很有用:http://automapper.org/ – Oxillery

Tony Hopkinson's answer是正确的你正在得到当前错误的原因。但是,它目前并未解决您所暗示的更大问题。

报价:Oxillery

注:如果“移植”从一个到另一个对象的这种方法是完全荒谬的 pleasegive我一些方向应该怎么做。这是我第一次尝试 这样的事情。

看来您正在接收一个序列化类实例(来自Web服务)的集合,并且希望将它们变为实体框架兼容对象。我相信你的问题会出现,因为你的实例的序列化和反序列化之间不一致。

看看下面的简单类(我们所期望的实体框架实体):

public class Dog 
{ 
    /// <summary> 
    /// The unique ID of this dog, aka the number printed on the dog's implanted microchip. 
    /// </summary> 
    [Key] 
    public int Id { get; set; } 

    public DateTime Birthday { get; set; } 

    public string Name { get; set; } 

    /// <summary> 
    /// The embarassing number of homeworks shredded. 
    /// </summary> 
    public long ShreddedHomeworks { get; set; } 
} 

根据您的说法,您是从Web服务接收某种其他物体要转换成狗。假设类您收到类似下面的长相:

public class PseudoDog 
{ 
    public DateTime Birthday { get; set; } 

    public string Name { get; set; } 

    public int Legs { get; set; } 
} 

请注意,这两个类都没有在序列化PseudoDog和反序列化它作为狗的条款直接兼容。我故意让PseudoDog拥有“腿”作为财产,而Dog拥有'ShreddedHomeworks',这样在没有操纵的情况下,它们就不能转化。

它们如何转换的基础来自关于数据传输对象(DTO)的Web API tutorial及其用法。继续上面的示例,用于将PseudoDog转换为狗的类将如下所示:

using System.Runtime.Serialization; 

[DataContract] 
public class DogDTO 
{ 
    #region Static Methods 

    public static Dog ToDog(DogDTO dto) 
    { 
     // if the data transfer object is null 
     // we cannot make a Dog from it. 
     if (dto == null) 
     { 
      return null; 
     } 

     Dog dog = new Dog(); 

     // We can be sure of what these values are intended to be. 
     dog.Name = dto.Name; 
     dog.Birthday = dto.Birthday; 

     return dog; 
    } 

    public static DogDTO CreateFrom(Dog dog) 
    { 
     if (dog == null) 
     { 
      return null; 
     } 

     DogDTO dto = new DogDTO(); 

     dto.Name = dog.Name; 
     dto.Birthday = dog.Birthday; 
    } 

    #endregion 

    [DataMember] 
    public DateTime Birthday { get; set; } 

    [DataMember] 
    public string Name { get; set; } 
} 

DogDTO的多汁的位被两个特性在具有底部(生日名称) DataMember属性。这意味着DogDTO类可以使用DataContractSerializer进行序列化和反序列化。

把所有的作品一起,整个过程是这样的:

  1. 一些客户端发出名为“菲多”
  2. 客户端序列化“菲”(XML有PseudoDog例如,JSON,二进制,等等...)到文件名为'serialdog.xml'。
  3. 客户端发送webservice'serialdog.xml'文件。
  4. 接收“serialdog.xml” WebService的反序列化到一个DogDTO实例(名为“FidoDTO”)
  5. 你的方法调用DogDTO.ToDog(FidoDTO),返回名为“myFido”新狗实例。
  6. 您现在可以使用Dog实例'myFido',因为它是实体框架实体。

Succintly,转换是这样的:

Web Service object --> object DTO --> Entity Framework compliant object 

在以下假设

A型 - 实例从Web服务

类型的类型A1 - 您当前转换实例的类型

B型 - 实例的由实体框架

类型A_DTO使用的类型 - 数据传输对象的类型

你应该做如下修改无论您身在何处,您都有此代码:

List<A1> allA1 = new List<A1>(); 
foreach (A item in retrievedListOfA) 
{  
    allA1.Add((A1)item); 
} 

我会用它代替它:

List<B> allB = new List<B>(); 
foreach (A_DTO dto in retrievedListofA_DTO) 
{ 
    allB.Add(A_DTO.ToB(dto)); 
}