2

我基本上想做的是将我从 Web 服务获得的对象转换为与我的实体框架对象兼容的对象。我想通过创建一个同时应用于 Web 服务对象和 EF 对象的接口来做到这一点。这样我就可以轻松地从一种类型转换为另一种类型。此时我有以下对象:A、A1、B 和接口 IAB。

我没有面临的问题是,当我从对象 A 向上转换到 A1 时,我得到一个运行时错误,但没有编译错误。我想知道为什么我的upcast不被接受?

public class A
{
  //Has variables & Properties
}

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

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

联系服务时,我要求提供 A 对象的列表,然后想将它们上载到 A1。稍后我会将它们转换为 B。

我尝试像这样投射对象:

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

由于我没有收到任何编译错误,我发现收到此错误很奇怪。如果我检查“A 是 A1”类型,那么它永远不会出现在那个 if 语句中。

有人可以向我指出为什么这会造成问题吗?是因为对象 A 来自 Web 服务吗?

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

4

2 回答 2

2

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

因此,如果 retrievedListOfA 是 As 和 A1 的集合,那么您将每个 A 转换为 A1,即实际上是一个 A,然后调用 A1 方法就会爆炸。

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

于 2013-07-18T16:24:32.730 回答
1

关于您收到当前错误的原因,托尼霍普金森的回答是正确的。但是,它目前并未解决您暗示的更大问题。

Quote:氧气

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

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

采用以下简单类(我们想要的 Entity Framework 实体):

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 服务接收某种您想要转换为 Dog 的其他对象。假设您收到的课程如下所示:

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

    public string Name { get; set; }

    public int Legs { get; set; }
}

请注意,这两个类在序列化 PseudoDog 和将其反序列化为 Dog 方面并不直接兼容。我故意让 PseudoDog 具有“腿”作为属性,而 Dog 具有“ShreddedHomeworks”,这样如果不进行操作,它们就无法转换。

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

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 的多汁位是底部的两个属性(BirthdayName),它们具有 DataMember 属性。这意味着可以使用 DataContractSerializer 对 DogDTO 类进行序列化和反序列化。

将所有部分放在一起,整个过程如下所示:

  1. 一些客户端创建了一个名为“Fido”的 PseudoDog 实例
  2. 客户端将“Fido”(到 XML、JSON、二进制等)序列化为名为“serialdog.xml”的文件。
  3. 客户端向 Web 服务发送“serialdog.xml”文件。
  4. 接收“serialdog.xml”的网络服务将其反序列化为 DogDTO 实例(名为“FidoDTO”)
  5. 您的方法调用 DogDTO.ToDog(FidoDTO),它返回一个名为“myFido”的新 Dog 实例。
  6. 您现在可以使用 Dog 实例“myFido”,因为它是一个实体框架实体。

简而言之,转换是这样的:

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

在以下假设下

Type A - 来自 Web 服务的实例的类型

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

Type B - 实体框架使用的实例的类型

Type 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));
}
于 2013-07-19T15:37:07.870 回答