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服务?
注意:如果这种“移植”对象从一个到另一个的方法是完全荒谬的,请给我一些指示应该如何完成。这是我第一次尝试这样的事情。
你没有得到任何编译错误,因为(A1)项,你是在对编译器说,我知道我在做什么,所以闭嘴。
因此,如果retrieveListOfA是一个As和A1s的集合,那么每个您投入到A1的A,实际上是一个A然后调用一个A1方法就会爆炸。
有很多移植方法,例如,一个转换器,铸造不是其中之一。
铸件确实不是一种方法,谢谢你的建议!我看了一下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进行序列化和反序列化。
把所有的作品一起,整个过程是这样的:
- 一些客户端发出名为“菲多”
- 客户端序列化“菲”(XML有PseudoDog例如,JSON,二进制,等等...)到文件名为'serialdog.xml'。
- 客户端发送webservice'serialdog.xml'文件。
- 接收“serialdog.xml” WebService的反序列化到一个DogDTO实例(名为“FidoDTO”)
- 你的方法调用DogDTO.ToDog(FidoDTO),返回名为“myFido”新狗实例。
- 您现在可以使用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));
}
就个人而言,我不会直接使用来自webservice的对象。我会考虑为“A”创建一个本地实体(比如localA)。也从一个来自webservice的对象继承是一个坏主意。 – Krishna
检查什么是异常时'项目'的类型 –