首页 > 解决方案 > c#继承和ISerialize接口

问题描述

我正在尝试对动物列表(猫或狗)进行二进制格式化。这在某种程度上很好。我在我的基类 Animal 中使用了 ISerialize 接口。两个派生类 dog 和 cat,但是它们都具有基类所没有的 1 个额外属性。现在,基类动物的序列化和反序列化没有给我带来任何问题。当我尝试序列化和反序列化前面提到的派生类中的任何一个额外属性时,问题就开始了。我觉得有一个简单的解决方法,但我正在监督一些事情。

下面我将发布以下位置的代码:

  1. Animal 类中的 ISerialize 接口
  2. Dog 类中的 ISerialize 接口
  3. Cat 类中的 ISerialize 接口
  4. Administration类中序列化器和反序列化器的实现(两者都绑定到表单中的两个按钮,所以我可以执行它们)
  5. Visual Studio 向我抛出的错误(荷兰语文本的翻译:“未找到成员不良习惯”)

我提前感谢您对此问题的任何评论和/或解决方案。

[Serializable()]
abstract public class Animal : ISellable, IComparable<Animal>, ISerializable
{
    /// <summary>
    /// The chipnumber of the animal. Must be unique. Must be zero or greater than zero.
    /// </summary>
    public int ChipRegistrationNumber { get; private set; }
    public abstract decimal Price { get; }

    /// <summary>
    /// Date of birth of the animal.
    /// </summary>
    public SimpleDate DateOfBirth { get; private set; }

    /// <summary>
    /// The name of the animal.
    /// </summary>
    public string Name { get; private set; }

    /// <summary>
    /// Is the animal reserved by a future owner yes or no.
    /// </summary>
    public bool IsReserved { get; set; }

    /// <summary>
    /// Creates an animal.
    /// </summary>
    /// <param name="chipRegistrationNumber">The chipnumber of the animal. 
    ///                                      Must be unique. Must be zero or greater than zero.</param>
    /// <param name="dateOfBirth">The date of birth of the animal.</param>
    /// <param name="name">The name of the animal.</param>
    public Animal(int chipRegistrationNumber, SimpleDate dateOfBirth, string name)
    {
        if (chipRegistrationNumber < 0)
        {
            throw new ArgumentOutOfRangeException("Chipnummer moet groter of gelijk zijn aan 0");
        }

        ChipRegistrationNumber = chipRegistrationNumber;

        DateOfBirth = dateOfBirth;

        if (name == null)
        {
            throw new ArgumentNullException("Naam is null");
        }

        Name = name;
        IsReserved = false;
    }

    /// <summary>
    /// Retrieve information about this animal
    /// 
    /// Note: Every class inherits (automagically) from the 'Object' class,
    /// which contains the virtual ToString() method which you can override.
    /// </summary>
    /// <returns>A string containing the information of this animal.
    ///          The format of the returned string is
    ///          "<ChipRegistrationNumber>, <DateOfBirth>, <Name>, <IsReserved>"
    ///          Where: IsReserved will be "reserved" if reserved or "not reserved" otherwise. 
    /// </returns>
    public override string ToString()
    {
        string IsReservedString;

        if (IsReserved)
        {
            IsReservedString = "reserved";
        }
        else
        {
            IsReservedString = "not reserved";
        }

        string info = ChipRegistrationNumber
                      + ", " + DateOfBirth
                      + ", " + Name
                      + ", " + IsReservedString;
        return info;
    }

    private Animal(SerializationInfo info, StreamingContext context)
    {
        ChipRegistrationNumber = (Int32)info.GetValue("Chipnumber", typeof(Int32));
        DateOfBirth = (SimpleDate)info.GetValue("Date of Birth", typeof(SimpleDate));
        Name = (String)info.GetValue("Name", typeof(String));
        IsReserved = (bool)info.GetValue("Isreserved", typeof(bool));
    }

    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue("Chipnumber", ChipRegistrationNumber);
        info.AddValue("Date of Birth", DateOfBirth);
        info.AddValue("Name", Name);
        info.AddValue("Isreserved", IsReserved);
    }

    public int CompareTo(Animal other)
    {
        throw new NotImplementedException();
    }
}

[Serializable]
public class Dog : Animal
{
    /// <summary>
    /// The date of the last walk of the dog. Contains null if unknown.
    /// </summary>
    public SimpleDate LastWalkDate { get; set; }

    /// <summary>
    /// Creates a dog.
    /// </summary>
    /// <param name="chipRegistrationNumber">The chipnumber of the animal. 
    ///                                      Must be unique. Must be zero or greater than zero.</param>
    /// <param name="dateOfBirth">The date of birth of the animal.</param>
    /// <param name="name">The name of the animal.</param>
    /// <param name="lastWalkDate">The date of the last walk with the dog or null if unknown.</param>
    public Dog(int chipRegistrationNumber, SimpleDate dateOfBirth,
               string name, SimpleDate lastWalkDate) : base(chipRegistrationNumber, dateOfBirth, name)
    {
        if (lastWalkDate != null)
        {
            this.LastWalkDate = lastWalkDate;
        }
    }

    /// <summary>
    /// Retrieve information about this dog
    /// 
    /// Note: Every class inherits (automagically) from the 'Object' class,
    /// which contains the virtual ToString() method which you can override.
    /// </summary>
    /// <returns>A string containing the information of this animal.
    ///          The format of the returned string is
    ///          "Dog: <ChipRegistrationNumber>, <DateOfBirth>, <Name>, <IsReserved>, <LastWalkDate>"
    ///          Where: IsReserved will be "reserved" if reserved or "not reserved" otherwise.
    ///                 LastWalkDate will be "unknown" if unknown or the date of the last doggywalk otherwise.
    /// </returns>
    public override string ToString()
    {
        // TODO: Put your own code here to make the method return the string specified in the
        // method description.
        if (LastWalkDate == null)
        {
            return $"Dog: {base.ToString()} - unknown";
        }
        return $"Dog: {base.ToString()}, {LastWalkDate}";
    }

    public override decimal Price
    {
        get
        {
            if(ChipRegistrationNumber < 50000)
            {
                return 200;
            }

            return 350;
        }
    }

    public new void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue("Lastwalk", LastWalkDate);
    }

    public Dog(SerializationInfo info, StreamingContext context) : base(info, context)
    {
        LastWalkDate = (SimpleDate)info.GetValue("Lastwalk", typeof(SimpleDate));
    }
}

[Serializable]
public class Cat : Animal
{
    /// <summary>
    /// Description of the bad habits that the cat has (e.g. "Scratches the couch").
    /// or null if the cat has no bad habits.
    /// </summary>
    public string BadHabits { get; set; }

    /// <summary>
    /// Creates a cat.
    /// </summary>
    /// <param name="chipRegistrationNumber">The chipnumber of the animal. 
    ///                                      Must be unique. Must be zero or greater than zero.</param>
    /// <param name="dateOfBirth">The date of birth of the animal.</param>
    /// <param name="name">The name of the animal.</param>
    /// <param name="badHabits">The bad habbits of the cat (e.g. "scratches the couch")
    ///                         or null if none.</param>
    public Cat(int chipRegistrationNumber, SimpleDate dateOfBirth,
               string name, string badHabits) : base(chipRegistrationNumber, dateOfBirth, name)
    {
        this.BadHabits = badHabits;
    }

    /// <summary>
    /// Retrieve information about this cat
    /// 
    /// Note: Every class inherits (automagically) from the 'Object' class,
    /// which contains the virtual ToString() method which you can override.
    /// </summary>
    /// <returns>A string containing the information of this animal.
    ///          The format of the returned string is
    ///          "Cat: <ChipRegistrationNumber>, <DateOfBirth>, <Name>, <IsReserved>, <BadHabits>"
    ///          Where: IsReserved will be "reserved" if reserved or "not reserved" otherwise.
    ///                 BadHabits will be "none" if the cat has no bad habits, or the bad habits string otherwise.
    /// </returns>
    public override string ToString()
    {
        // TODO: Put your own code here to make the method return the string specified in the
        // method description.
        if (String.IsNullOrEmpty(BadHabits))
        {
            BadHabits = "none";
        }

        return $"{"Cat: "}{base.ToString()}, {BadHabits}";
    }

    public override decimal Price
    {
        get
        {
            int korting = BadHabits.Length - 60;
            if ( korting > 20)
            {
                return korting;
            }

            return 20;
        }
    }

    public new void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue("BadHabits", this.BadHabits);
    }
    public Cat(SerializationInfo info, StreamingContext context) : base(info, context)
    {
        this.BadHabits = (String)info.GetString("BadHabits");
    }
}

行政

    public void Save(String fileName)
    {
        Stream fileStream = File.Open(fileName, FileMode.Create);
        BinaryFormatter format = new BinaryFormatter();
        format.Serialize(fileStream, Animals);
        fileStream.Close();
    }

    public void Load(String fileName)
    {
        FileStream fileStream;
        BinaryFormatter format = new BinaryFormatter();
        fileStream = File.OpenRead(fileName);
        Animals = (List<Animal>)format.Deserialize(fileStream);
        fileStream.Close();
    }

错误信息

标签: c#inheritanceserializationinterfacedeserialization

解决方案


问题是您的子方法中的“新”部分。通过在子类上写“新”,继承方法的实现将被隐藏。

构造函数编写得当,方法是问题所在。

这是解决此问题的一种方法:

class Animal
{
   ...
   public virtual GetObjectData(... params ...)
   {
     // populate properties
   }
   ...
}

class Dog
{
    public override GetObjectData(... params ...)
    {
      base.GetObjectData(... params ...)
      // populate additional Dog properties
    }
}

推荐阅读