I have the following exception in my code in CSharp:
The serializer doesnt take count the serialization of generic types: System.Collections.Generic.SortedSet`
Here is my code which is problematic(in the class FileStreamer):
public static bool SoapSave(SortedSet<T> set, string filename)
{
FileStream stream = File.Create(filename);
SoapFormatter formatter = new SoapFormatter();
formatter.Serialize(stream, set);
stream.Close();
return true;
}
Here is the following class I used in my project:
The main class:
class Program
{
public static void Main(string[] args)
{
GestAuthentification ga = new Authentification () ;
try
{
ga.addUser("bob","123");
ga.removeUser("bob");
ga.removeUser("bob");
} catch (UserUnknown e) {
Console.WriteLine(e.Login +" est inconnu du système! on ne peut le retirer.");
} catch (UserExists e) {
Console.WriteLine(e.Login +" est déjà dans le système! on ne peut le recréer.");
}
try
{
ga.addUser("bob","123");
ga.authentify("bob","123");
ga.authentify("bob","456");
} catch (WrongPassword e) {
Console.WriteLine(e.Login+" s'est trompé de password !");
} catch (UserExists e) {
Console.WriteLine(e.Login +" est déjà dans le système! on ne peut le recréer.");
} catch (UserUnknown e) {
Console.WriteLine(e.Login +" est inconnu du système! on ne peut le retirer.");
}
//Until here it works
try
{
ga.save("users.txt");
GestAuthentification gb = new Authentification();
gb.load("users.txt");
gb.authentify("bob","123");
Console.WriteLine("Test sauvegarde/chargement réussi !");
} catch (UserUnknown e) {
Console.WriteLine(e.Login +" est n'est plus connu. Problème de sauvegarde/chargement.");
} catch (WrongPassword e) {
Console.WriteLine(e.Login+" s'est trompé de password !Problème de sauvegarde/chargement.");
} catch (IOException e) {
Console.WriteLine(e);
}
}
}
Authentification.cs
[Serializable]
public class Authentification: GestAuthentification
{
private SortedSet<User> userset;
public Authentification()
{
this.userset = new SortedSet<User>();
}
public void addUser(String login, String pass)
{
if (userset.Count() == 0)
{
User usr0 = new User(login, pass);
userset.Add(usr0);
Console.WriteLine(usr0._login + " a été ajoute");
return;
}
else
{
foreach (User u in userset)
{
if (u._login.Equals(login))
{
throw new UserExists(u);
}
}
User usr = new User(login, pass);
userset.Add(usr);
Console.WriteLine(usr._login + " a été ajoute");
}
}
public void removeUser(String login)
{
foreach (User u in userset)
{
if (u._login.Equals(login))
{
userset.Remove(u);
Console.WriteLine(u._login + " a été retiré.");
return;
}
}
User usr = new User(login,"");
throw new UserUnknown(usr);
}
public void authentify(String login, String Pass)
{
foreach (User u in userset)
{
if (u._login.Equals(login)&&u._password.Equals(Pass))
{
Console.WriteLine(u._login + " a été authenthifié.");
return;
}
else if((u._login.Equals(login))&&(u._password.Equals(Pass)==false))
{
throw new WrongPassword(u);
}
}
User usr = new User(login, "");
throw new UserUnknown(usr);
}
public void load(String path)
{
FileStreamer<User>.SoapLoad(path);
}
public void save(String path)
{
FileStreamer<User>.SoapSave(userset, path);
}
}
FileStreamer.cs
public class FileStreamer<T>
{
public static bool SoapSave(SortedSet<T> set, string filename)
{
FileStream stream = File.Create(filename);
SoapFormatter formatter = new SoapFormatter();
formatter.Serialize(stream, set);
stream.Close();
return true;
}
public static SortedSet<T> SoapLoad(string filename)
{
FileStream stream = File.OpenRead(filename);
SoapFormatter formatter = new SoapFormatter();
SortedSet<T> set = (SortedSet<T>)formatter.Deserialize(stream);
stream.Close();
return set;
}
}
User.cs
public class User: IComparable<User>
{
private string login;
private string password;
public string _login
{
get{return login;}
set {login=value;}
}
public string _password
{
get { return password; }
set { password = value; }
}
public User(string l, string p)
{
login = l;
password = p;
}
public int CompareTo(User u)
{
if(login.CompareTo(u._login)>0)
{
return 1;
}
else if(login.CompareTo(u._login)==0)
{
return 0;
}
else
{
return -1;
}
}
}
So where are the problem with the serialization in my project, and how to correct it ?
Thanks.
You're likely to encounter any number of problems using SoapFormatter
in a modern .Net context. From the docs:
Beginning with the .NET Framework 2.0, this class is obsolete. Use BinaryFormatter instead.
That being said, as you have noticed, SoapFormatter
does not support generics. It does, however, support arrays, arrays having existed as far back as .Net 1. Thus you can serialize your SortedSet<T>
as an array:
public class FileStreamer<T>
{
static void SoapSave(SortedSet<T> set, Stream stream)
{
var formatter = new SoapFormatter();
formatter.Serialize(stream, set.ToArray());
}
public static SortedSet<T> SoapLoad(Stream stream)
{
var formatter = new SoapFormatter();
var array = (T [])formatter.Deserialize(stream);
return new SortedSet<T>(array);
}
public static bool SoapSave(SortedSet<T> set, string filename)
{
using (var stream = File.Create(filename))
{
SoapSave(set, stream);
}
return true;
}
public static SortedSet<T> SoapLoad(string filename)
{
using (var stream = File.OpenRead(filename))
{
return SoapLoad(stream);
}
}
}
Note SoapFormatter
also requires that you mark your User
class as [Serializable]
:
[Serializable]
public class User : IComparable<User>
{
// Remainder of the class unchanged.
}