如何构造类来实现IEquatable和ISerializable

时间:2010-08-10 06:46:20

标签: c# iequatable iserializable

现在已经暂时搁置了一段时间

我遇到的问题是尝试添加IEquatable行为,因此我的派生类可以使用ILink等的集合操作Intersect。

此刻我......

public interface ILink
{
    int Linkid { get; set; }
    bool IsActive { get; set; }
}

和一堆派生类,如

public class Domain : ILink
{
     public Domain(){}
}


public class User : ILink 
{
      public User (){}
}

所以为了做列表的交集 我以为我会像这样创建一个抽象类......

public abstract class AbstractLink : IEquatable<ILink>, ISerializable, ILink
{

    public AbstractLink(){}

    public AbstractLink(SerializationInfo info, StreamingContext ctxt)
    {}
    public virtual void GetObjectData(SerializationInfo info, StreamingContext ctxt)
    {}

}

然而,当我从

更改派生类型时
 public class DomainLink : ILink
 {

 }

 public class DomainLink : AbstractLink
 {

 }

我收到一个SerializationException“找不到会员'Linkid'。”这是它尝试反序列化的第一个成员

BTW:这是Remoting因此需要自定义序列化 - 有没有办法将这些行为组合在一起?

非常感谢!

中号

1 个答案:

答案 0 :(得分:1)

您的示例代码无法编译。您没有实现ILink接口成员。

以下代码确实有效。

覆盖AbstractLink的每个对象都需要一个序列化构造函数。 AbstractLink的每个子类也需要使用[Serializable]进行注释。如果向域对象添加额外属性,则还需要为额外属性实现GetObjectData()。

using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

public interface ILink
{
    int Linkid { get; set; }
    bool IsActive { get; set; }
}

[Serializable]
public class Domain : AbstractLink
{
    public Domain()
    {
    }

    public Domain(SerializationInfo info, StreamingContext ctx) 
        : base(info, ctx)
    {
    }
}

[Serializable]
public class User : AbstractLink
{
    public string UserName { get; set; }

    public User()
    {
    }

    public User(SerializationInfo info, StreamingContext ctx) 
        : base(info, ctx)
    {
        UserName = info.GetString("UserName");
    }

    public override void GetObjectData(SerializationInfo info, StreamingContext ctx)
    {
        base.GetObjectData(info, ctx);
        info.AddValue("UserName", UserName);
    }
}

public abstract class AbstractLink : ISerializable, ILink, IEquatable<ILink>
{
    public AbstractLink() { }

    public AbstractLink(SerializationInfo info, StreamingContext ctx)
    {
        Linkid = info.GetInt32("Linkid");
        IsActive = info.GetBoolean("IsActive");
    }

    public virtual void GetObjectData(SerializationInfo info, StreamingContext ctx)
    {
        info.AddValue("Linkid", Linkid);
        info.AddValue("IsActive", IsActive);
    }

    public bool Equals(ILink other)
    {
        if (ReferenceEquals(null, other))
            return false;

        if (ReferenceEquals(this, other))
            return true;

        return other.Linkid == Linkid && other.IsActive.Equals(IsActive);
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj))
            return false;

        if (ReferenceEquals(this, obj))
            return true;

        return obj.GetType() == typeof(AbstractLink) && Equals((AbstractLink) obj);
    }

    public override int GetHashCode()
    {
        unchecked
        {
            return (Linkid * 397) ^ IsActive.GetHashCode();
        }
    }

    public int Linkid { get; set; }
    public bool IsActive { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        var user = new User { UserName = "user", IsActive = true, Linkid = 1 };
        User user2;

        using (var ms = new MemoryStream())
        {
            var bf = new BinaryFormatter();
            bf.Serialize(ms, user);
            ms.Flush();

            ms.Seek(0, SeekOrigin.Begin);
            user2 = bf.Deserialize(ms) as User;
        }

        Debug.Assert(user2 != null);
        Debug.Assert(ReferenceEquals(user, user2) == false);
        Debug.Assert(Equals(user.Linkid, user2.Linkid));
        Debug.Assert(Equals(user.IsActive, user2.IsActive));
        Debug.Assert(Equals(user.UserName, user2.UserName));
    }
}