Сериализация C # через сокет, один класс сериализуется, другой нет

#c# #sockets #serialization #stream #formatter

#c# #сокеты #сериализация #поток #форматировщик

Вопрос:

я пытаюсь создать для школьного проекта клиент-серверное приложение на C #, моя проблема в том, что один класс сериализуется нормально и отправляется через сокет, а другой — нет, и я не могу в этом разобраться.

Класс Employee (а также Bonus) сериализуется, но когда я пытаюсь передать программе форматирования экземпляр Transfer

 formatter.Serialize(stream, transferObj);
  

это вызывает исключение: NotSupportedException
с сообщением: поток памяти не может быть расширен.

sendToServer()

  Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        System.Net.IPAddress ipAdd = System.Net.IPAddress.Parse("127.0.0.1");
        System.Net.IPEndPoint remoteEP = new IPEndPoint(ipAdd, 6666);
        socket.Connect("127.0.0.1", 6666);


        Transfer t = new Transfer();

        Employee e = new Employee(); 
        Bonus b = new Bonus(); b.setAmmount(234); b.setDescription("xxxx");
        e.getBonuses().Add(b);

        byte[] buffer = new byte[1000];
        System.Console.WriteLine("client started");

            IFormatter formatter = new BinaryFormatter();
            Stream stream = new MemoryStream(buffer);


            formatter.Serialize(stream, e);
             // Employee and Bonus are serialized but not Transfer
            stream.Flush();

            socket.Send(buffer,buffer.Length,0);
  

Класс Employee

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Permissions;
using System.Runtime.Serialization;

namespace Entity
{
[Serializable]
public class Employee : ISerializable
{

    private int id;
    private long version;
    private String username;
    private String password;
    private String role;
    private String name;
    private String surname;
    private long salary;
    private DateTime experience;
    private DateTime birthDate;
    private String sex;
    private List<Bonus> bonuses;

    public Employee() {
        bonuses = new List<Bonus>();
    }

       protected Employee(SerializationInfo info, StreamingContext context)
    {
        id = info.GetInt32("id");
        version = info.GetInt32("version");
        username = info.GetString("username");
        password = info.GetString("password");
        role = info.GetString("role");
        name = info.GetString("name");
        surname = info.GetString("surname");
        salary = info.GetInt32("salary");
        experience = (DateTime) info.GetValue("exp", typeof(DateTime));
        birthDate = (DateTime)info.GetValue("birth", typeof(DateTime));
        sex = info.GetString("sex");
        bonuses = (List<Bonus>) info.GetValue("bonuses", typeof(List<Bonus>));

    }





    public int getId()
    {
        return id;
    }
    public void setId(int id)
    {
        this.id = id;
    }
    public String getName()
    {
        return name;
    }
    public void setName(String name)
    {
        this.name = name;
    }
    public String getSurname()
    {
        return surname;
    }
    public void setSurname(String surname)
    {
        this.surname = surname;
    }
    public long getSalary()
    {
        return salary;
    }
    public void setSalary(long salary)
    {
        this.salary = salary;
    }
    public DateTime getExperience()
    {
        return experience;
    }
    public void setExperience(DateTime experience)
    {
        this.experience = experience;
    }
    public DateTime getBirthDate()
    {
        return birthDate;
    }
    public void setBirthDate(DateTime birthDate)
    {
        this.birthDate = birthDate;
    }
    public List<Bonus> getBonuses()
    {
        return bonuses;
    }
    public void setBonuses(List<Bonus> bonuses)
    {
        this.bonuses = bonuses;
    }


    public override string ToString()
    {
        return name   " "   surname;
    }

    public override int GetHashCode()
    {
        int prime = 31;
        int result = 1;
        result = prime * result   id;
        return resu<
    }

    public override bool Equals(System.Object obj)
    {
        // If parameter is null return false.
        if (obj == null)
        {
            return false;
        }

        // If parameter cannot be cast to Point return false.
        Employee p = obj as Employee;
        if ((System.Object)p == null)
        {
            return false;
        }

        // Return true if the fields match:
        return id == p.id;
    }

    public void setSex(String sex)
    {
        this.sex = sex;
    }
    public String getSex()
    {
        return sex;
    }
    public long getVersion()
    {
        return version;
    }
    public void setVersion(long version)
    {
        this.version = version;
    }
    public String getUsername()
    {
        return username;
    }
    public void setUsername(String username)
    {
        this.username = username;
    }
    public String getPassword()
    {
        return password;
    }
    public void setPassword(String password)
    {
        this.password = password;
    }
    public String getRole()
    {
        return role;
    }
    public void setRole(String role)
    {
        this.role = role;
    }

    #region ISerializable Members
    [SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)]
    void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue("id", id);
        info.AddValue("version", version);
        info.AddValue("username", username);
        info.AddValue("password", password);
        info.AddValue("role", role);
        info.AddValue("name", name);
        info.AddValue("surname", surname);
        info.AddValue("salary", salary);
        info.AddValue("exp", experience);
        info.AddValue("birth", birthDate);
        info.AddValue("sex", sex);
        info.AddValue("bonuses", bonuses);
    }

    #endregion
}

}
  

Передача класса

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Permissions;
using System.Runtime.Serialization;


namespace Entity
{
[Serializable]
public class Transfer : ISerializable
{
    private Employee employee;
    private String method;
    private String message;
    private List<Employee> queriedEmployees;

    public Transfer() {
        queriedEmployees = new List<Employee>();
    }

    protected Transfer(SerializationInfo info, StreamingContext context)
    {

        employee = (Employee) info.GetValue("employee", typeof(Employee) );
        method = info.GetString("method");
        message = info.GetString("message");
        queriedEmployees = (List<Employee>) info.GetValue("qe", typeof(List<Employee>));
    }






    public Employee getEmployee() 
    {
        return employee;
    }

    public String getMethod()
    {
        return method;
    }

    public String getMessage()
    {
        return message;
    }

    public List<Employee> getQueriedEmployees()
    {
        return queriedEmployees;
    }

    public void setEmployee(Employee e)
    {
        employee = e;
    }

    public void setMessage(String mes)
    {
        message = mes;
    }

    public void setMethod(String meth)
    {
        method = meth;
    }

    public void setQueriedEmployees(List<Employee> elist)
    {
        queriedEmployees = elist;
    }



    #region ISerializable Members
    [SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)]
    void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue("employee", employee);
        info.AddValue("method", method);
        info.AddValue("message", message);
        info.AddValue("qe", queriedEmployees);
    }

    #endregion
}
}
  

Комментарии:

1. В дополнение к ответам обратите внимание, что отправка всего буфера неверна; вы должны использовать только используемую часть буфера — т. Е. Проверить длину потока памяти. Также обратите внимание, что в большинстве случаев вы можете записывать непосредственно в выходной поток, не прибегая к искусственному буферу посередине.

Ответ №1:

Это не позволяет вам, потому что вы явно инициализируете MemoryStream массивом байтов фиксированной длины. Смотрите это: http://weblogs.asp.net/ashicmahtab/archive/2008/08/25/memorystream-not-expandable-invalid-operation-exception.aspx

Попробуйте что-то вроде этого вместо:

             IFormatter formatter = new BinaryFormatter();
            Stream stream = new MemoryStream();


            formatter.Serialize(stream, e);
            byte[] buffer = ((MemoryStream)stream).ToArray();
  

Ответ №2:

Предоставляя буфер конструктору MemoryStream, вы фиксируете его до этого размера. Если вы просто используете конструктор по умолчанию, поток должен быть расширяемым до любого требуемого размера.

 Stream stream = new MemoryStream();
  

Смотрите эту запись в блоге

Ответ №3:

установка большего буфера позволит мне сериализовать класс передачи