Używam BinaryFormatter
do serializacji binarnej niektórych obiektów w języku C#. Jednak niektóre obiekty zawierają klasy, do których uzyskuję dostęp za pośrednictwem biblioteki DLL i nie mają kodu źródłowego, więc nie mogę oznaczyć ich atrybutem Serializable
. Czy istnieje jakiś prosty sposób na serializowanie ich? Mam obejście, które obejmuje wzięcie klasy NoSource
i utworzenie nowej klasy SerializableNoSource
, dla której konstruktor pobiera obiekt NoSource
i wyodrębnia z niej wszystkie potrzebne informacje, ale jest zhakowany. Czy są jakieś lepsze alternatywy?Czy jest możliwe wykonanie serializacji binarnej .NET, gdy nie masz kodu źródłowego klasy?
Odpowiedz
Myślę, że czystszym sposobem byłoby implicment ISerializable Interface i zarządzanie serializacją i procesem odwrotnym. W MSDN możemy znaleźć:
serializacji nie może zostać dodany do klasy po jej skompilowany ....
"Jednak niektóre obiekty zawierają klasy, do których uzyskuję dostęp przez bibliotekę DLL i nie mają kodu źródłowego dla" –
Możesz myśleć, że tworzę własną klasę, która może mieć takie same właściwości jak obiekt, w którym nie masz źródła Nie? Lub rozszerza to? –
Rozszerzenie nie działa, kopiowanie właściwości ... to jest to samo, co teraz ma teraz –
Możesz być w stanie wykorzystać Mono.Cecil dodać [SerializableAttribute]
do klas , ale nie zrobiłbym tego, jeśli istnieje inny sposób osiągnięcia pożądanego rezultatu.
Zgadzam się z @Servy, jeśli autor klasy nie spodziewał się, że będzie serializowany, nie należy próbować przekształcać go bezpośrednio do postaci szeregowej. Więc robisz to, co należy, z architektonicznego punktu widzenia. Aby zmniejszyć obecne podejście, "hacky", rozważ implementację ISerializable dla klas, które zawierają odniesienia do obiektów niezdolnych do serializacji.
Utwórz nową klasę, dziedzicz istniejącą klasę, która nie jest oznaczona atrybutem serializacji i implementuj interfejs ISerializable.
Jeśli zajęcia są zapieczętowane, możesz użyć Json.NET, a następnie przekonwertować je na wersję binarną i na odwrót (bardzo się przydaje, użyj go, jeśli nic innego nie pomoże :)).
Można utworzyć surogat serializacyjny .
Wyobraźmy sobie, że mamy klasy określone w wymienionej zespołu, że nie mamy kontroli nad, który wygląda tak:
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public DriversLicense License;
}
// An instance of this type will be part of the object graph and will need to be
// serialized also.
public class DriversLicense
{
public string Number { get; set; }
}
W celu serializacji ten cel trzeba będzie zdefiniować surogat serializacji dla każdego typu na wykresie obiektu.
Aby utworzyć surogat serializacji wystarczy stworzyć typ, który implementuje interfejs ISerializationSurrogate
:
public class PersonSurrogate : ISerializationSurrogate
{
/// <summary>
/// Manually add objects to the <see cref="SerializationInfo"/> store.
/// </summary>
public void GetObjectData(object obj, SerializationInfo info, StreamingContext context)
{
Person person = (Person) obj;
info.AddValue("Name", person.Name);
info.AddValue("Age", person.Age);
info.AddValue("License", person.License);
}
/// <summary>
/// Retrieves objects from the <see cref="SerializationInfo"/> store.
/// </summary>
/// <returns></returns>
public object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
{
Person person = (Person)obj;
person.Name = info.GetString("Name");
person.Age = info.GetInt32("Age");
person.License = (DriversLicense) info.GetValue("License", typeof(DriversLicense));
return person;
}
}
public class DriversLicenseSurrogate : ISerializationSurrogate
{
/// <summary>
/// Manually add objects to the <see cref="SerializationInfo"/> store.
/// </summary>
public void GetObjectData(object obj, SerializationInfo info, StreamingContext context)
{
DriversLicense license = (DriversLicense)obj;
info.AddValue("Number", license.Number);
}
/// <summary>
/// Retrieves objects from the <see cref="SerializationInfo"/> store.
/// </summary>
/// <returns></returns>
public object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
{
DriversLicense license = (DriversLicense)obj;
license.Number = info.GetString("Number");
return license;
}
}
Następnie trzeba pozwolić IFormatter
wiedzieć o surogatów poprzez definiowanie i inicjowanie SurrogateSelector
i przypisanie go do twój IFormatter
.
private static void SerializePerson(Person person)
{
if (person == null)
throw new ArgumentNullException("person");
using (var memoryStream = new MemoryStream())
{
//Configure our surrogate selectors.
var surrogateSelector = new SurrogateSelector();
surrogateSelector.AddSurrogate(typeof (Person), new StreamingContext(StreamingContextStates.All),
new PersonSurrogate());
surrogateSelector.AddSurrogate(typeof (DriversLicense), new StreamingContext(StreamingContextStates.All),
new DriversLicenseSurrogate());
//Serialize the object
IFormatter formatter = new BinaryFormatter();
formatter.SurrogateSelector = surrogateSelector;
formatter.Serialize(memoryStream, person);
//Return to the beginning of the stream
memoryStream.Seek(0, SeekOrigin.Begin);
//Deserialize the object
Person deserializedPerson = (Person) formatter.Deserialize(memoryStream);
}
}
Korzystanie z surogat serializacji nie jest wcale proste, a może rzeczywiście stać się bardzo gadatliwy, gdy typ próbujesz serializacji ma prywatne & chronionych obszarów, które muszą być w odcinkach.
Ale jak już ręcznie serializujesz potrzebne wartości, nie sądzę, że to jest problem.Używanie surogatu jest bardziej unifomicznym sposobem radzenia sobie z takim scenariuszem i powinno sprawić, że poczujesz się bardziej komfortowo.
To wygląda na odpowiedź podręcznika, aby naprawdę serializować unowned klasy, która nie jest oznaczona '[Serializable]' –
Jeśli chcesz więcej informacji możesz przeczytać rozdział 23 [CLR przez C#] (http://www.amazon.co.uk/CLR-via-C-Jeffrey-Richter/dp/0735627045) - Serializacja Runtime. –
Znaleźliśmy również odpowiedni artykuł na temat MSDN: http://msdn.microsoft.com/en-us/magazine/cc188950.aspx –
- 1. .NET Metadane serializacji binarnej
- 2. Czy jest możliwe wykonanie zestawu .NET (dll) z vbscript?
- 3. Global.asax nie może znaleźć kodu źródłowego klasy
- 4. Czy jest możliwe użycie funkcji jednoargumentowej zamiast binarnej w `flip`?
- 5. Czy możliwe jest przeglądanie plików klasy Java według kodu bajtowego
- 6. Pobieranie kodu źródłowego Eclipse
- 7. Eclipse: Czy możliwe jest edytowanie źródła Java znanego z kodu źródłowego "załącznik"
- 8. Czy w Protobuf-net możliwe jest serializowanie nieprzypisanych klas?
- 9. Czy możliwe jest wykonanie modułu w języku Python?
- 10. Arbitralne wykonanie polecenia - możliwe?
- 11. WPF: Czy jest możliwe wykonanie rozpiętości wiersza/kolumny w UniformGrid?
- 12. Czy można dodać punkty przerwania do klasy, dla której nie mam kodu źródłowego?
- 13. Debugowanie kodu źródłowego JBoss
- 14. Instalacja binarna django (bez kodu źródłowego)
- 15. Czy możliwe jest podłączenie kodu źródłowego do GHC za pomocą standardowego wejścia?
- 16. Czy jest możliwe wykonanie dwóch zapytań aktualizacji w phpmyadmin razem?
- 17. Czy jest możliwe wykonanie kompilacji poza źródłem przy użyciu bjam?
- 18. Czy możliwe jest wykonanie elementu samozamykającego w Angular 2?
- 19. Czy jest możliwe wykonanie instrukcji "LIKE" w wyrażeniu SSIS?
- 20. Dlaczego masz "gdzie", gdy jest "o"
- 21. C# Czy jest możliwe podanie lambda, gdy wymagany jest interfejs?
- 22. Wydajność DeepClone (przy użyciu serializacji binarnej) a ręczne ustawianie właściwości
- 23. Czy jest możliwe dynamiczne kompilowanie i wykonywanie fragmentów kodu C#?
- 24. Dziwne zachowanie serializacji binarnej .NET na Słowniku <Key, Value>
- 25. Czy umieszczasz kompilacje w repozytorium kodu źródłowego?
- 26. Wyświetlanie kodu źródłowego Gem
- 27. Popraw wydajność binarnej serializacji dla dużej listy struktur
- 28. nie jest JSON serializacji
- 29. Jakie są typy MIME dla plików kodu źródłowego projektu .NET?
- 30. Pobieranie kodu źródłowego Android
Dla zapisu, enkapsulacja obiektu w innym obiekcie, który * nie * wie, jak szeregować siebie, jak również konwersja do/z enkapsulowanego obiektu nie jest w moim umyśle hacky, jest całkowicie odpowiednia. Teraz może być coś lepszego lub lepszego, ale nie uważam, że twoje obecne podejście jest zasadniczo wadliwe. – Servy