Как структурировать классы для реализации IEquatable и ISerializable - PullRequest
0 голосов
/ 10 августа 2010

Некоторое время я уже думал об этом

Проблема, с которой я столкнулся, пытается добавить поведение IEquatable, чтобы мои производные классы могли использовать операции над множествами Intersect of ILink и т. Д.

Вв тот момент, когда у меня есть ...

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' былне найдено."который является первым членом, который пытается десериализовать

КСТАТИ: это Remoting, отсюда и необходимость пользовательской сериализации - есть ли способ объединить эти поведения вместе?

Большое спасибо!

M

1 Ответ

1 голос
/ 10 августа 2010

Ваш пример кода не компилируется. Вы не реализуете элементы интерфейса 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));
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...