Używamy XmlSerializer
i chcę zapewnić niestandardową serializację dla niektórych klas. Jednak nie zawsze mam możliwość modyfikowania kodu źródłowego danej klasy, w przeciwnym razie mógłbym po prostu dokonać implementacji IXmlSerializable
. Czy jest jakiś sposób to zrobić?Czy mogę zapewnić niestandardową serializację dla XmlSerializer bez implementacji IXmlSerializable?
Czy mogę zapewnić niestandardową serializację dla XmlSerializer bez implementacji IXmlSerializable?
Odpowiedz
Oto prosty przykład pomocnika deserializowania Proxy:
przypisany typ, że nie możemy bezpośrednio kontrolować serializacji na poziomie klasy:
public sealed class Class //contrived example
{
public string Property {get;set;}
}
a xml musimy deserializowania z:
<Class>
<Property>Value</Property>
</Class>
Można utworzyć typ proxy, aby ręcznie przeprowadzić proces deserializacji typu docelowego:
[XmlRoot("Class")] // <-- Very important
public sealed class ClassSerializerProxy : IXmlSerializable
{
public Class ClassValue {get;set;}
public System.Xml.Schema.XmlSchema GetSchema(){return null;}
public void WriteXml(System.Xml.XmlWriter writer){}
public void ReadXml(System.Xml.XmlReader reader)
{
var x = XElement.ReadFrom(reader) as XElement;
this.ClassValue = new Class();
//again this is a simple contrived example
this.ClassValue.Property = x.XPathSelectElement("Property").Value;
}
}
użycia:
void Main()
{
// get the xml value somehow
var xdoc= XDocument.Parse(@"<Class><Property>Value</Property></Class>");
// deserialize the xml into the proxy type
var proxy = Deserialize<ClassSerializerProxy>(xdoc);
// read the resulting value
var value = proxy.ClassValue;
}
public object Deserialize(XDocument xmlDocument, Type DeserializeToType)
{
XmlSerializer xmlSerializer = new XmlSerializer(DeserializeToType);
using (XmlReader reader = xmlDocument.CreateReader())
return xmlSerializer.Deserialize(reader);
}
teraz rzucać w niektórych leków generycznych i metodę rozszerzenia, a my możemy oczyścić witrynie Up Call trochę dla końcowego (z wyjątkiem Obsługa wyjątków) wersji:
Zastosowanie:
void Main()
{
var xml = @"<Class><Property>Value</Property></Class>";
var value = xml.DeserializeWithProxy<ClassSerializerProxy,Class>();
value.Dump();
}
Twój typ instancji:
public sealed class Class
{
public string Property {get;set;}
}
interfejs że typy proxy musi implementować
public interface ISerializerProxy<TInstanceType> where TInstanceType : class
{
TInstanceType Value { get; }
}
Przykład Pełnomocnik obecnie wprowadza nowy interfejs
[XmlRoot("Class")]
public sealed class ClassSerializerProxy : IXmlSerializable, ISerializerProxy<Class>
{
public Class Value {get;set;}
public System.Xml.Schema.XmlSchema GetSchema(){return null;}
public void WriteXml(System.Xml.XmlWriter writer){}
public void ReadXml(System.Xml.XmlReader reader)
{
var x = XElement.ReadFrom(reader) as XElement;
this.Value = new Class();
this.Value.Property = x.XPathSelectElement("Property").Value;
}
}
Sposób deserializacji jest teraz metodę rozszerzenia na string
i może być używany z dowolnym proxy rodzaj.
public static class ExtensionMethods
{
public static TInstanceType DeserializeWithProxy<TProxyType,TInstanceType>(this string xml)
where TProxyType : ISerializerProxy<TInstanceType>
where TInstanceType : class
{
using (XmlReader reader = XDocument.Parse(xml).CreateReader())
{
var xmlSerializer = new XmlSerializer(typeof(TProxyType));
return (xmlSerializer.Deserialize(reader) as ISerializerProxy<TInstanceType>).Value;
}
}
}
Czy istnieje sposób użycia tego podejścia, jeśli mam duże drzewo obiektów i chcę użyć domyślnej serializacji dla drzewa jako całości, ale niestandardową serializację dla niektórych liści? Jeśli mam dostęp do źródła, mogę sprawić, by te liście zaimplementowały IXmlSerializable i umieściły tam niestandardową serializację. Ale jeśli nie mogę zmodyfikować liści, czy muszę napisać kod serializacji dla całego drzewa? A może w jakiś sposób celuję w mały podzbiór klas problemów? – Rob
@asawyer To jest świetna odpowiedź! Zdecydowałem się również na wdrożenie funkcji WriteXml, ponieważ moja prawdziwa klasa nie jest sama w sobie możliwa do serializowania. Składa się z zestawu akcesorów tylko do odczytu, które można ustawić tylko za pomocą konstruktora. –
@nadephette Jestem bardzo szczęśliwy, że mogłem pomóc! – asawyer
- 1. Czy mogę dostosować serializację Json.NET bez adnotowania w moich klasach?
- 2. Jak zapewnić niestandardową obsadę dla mojej klasy?
- 3. Wdrażanie IXmlSerializable na obiekcie zbiórki
- 4. Jak mogę zapewnić ciąg alfanumeryczny bez znaku podkreślenia?
- 5. Jak mogę zapewnić implementację metod za pomocą Moq?
- 6. Jak zapewnić dodatkową inicjalizację dla podklasy namedtuple?
- 7. Walidacja xmlserializer
- 8. Czy XmlSerializer ucieka od znaków specjalnych, takich jak &?
- 9. W jaki sposób mogę zapewnić podstawowe uwierzytelnianie http dla webmasterów statycznych tomcatów bez zmiany tomcat-users.xml?
- 10. Jak mogę sprawdzić poprawność wyjścia XmlSerializer?
- 11. Jak mogę zapewnić implementację GetSizeForItem w UICollectionViewController?
- 12. Jak mogę zapewnić bezpieczeństwo wątków w następującym kontekście?
- 13. Czy można zapewnić intellisense dla dynamicznych obiektów w visual studio?
- 14. Czy mogę ustawić niestandardową licencję za pomocą WiX?
- 15. Jak mogę utworzyć niestandardową usługę czcionek dla języka perskiego?
- 16. Czy można zgłosić klasę bez jej implementacji? (C++)
- 17. jak napisać niestandardową regułę InlineLexer dla marked.js?
- 18. Jak dostosować serializację XML WCF
- 19. Czy istnieje kolejka implementacji?
- 20. Zastąp domyślną serializację JSON WCF
- 21. Zapewnić lokalną awaryjne dla CSS z CDN
- 22. Twórz niestandardową kulturę bez jej rejestrowania.
- 23. Jak używać niestandardowego IXmlSerializable jako XmlAttribute?
- 24. Funkcjonalność XmlSerializer w PowerShell?
- 25. Linq do Xml VS XmlSerializer VS DataContractSerializer
- 26. Czy mogę zastosować metody rozszerzeń do implementacji interfejsu?
- 27. Czy mogę kpić z implementacji interfejsu za pomocą PHPUnit?
- 28. Python mock - łatanie metody bez utrudniania implementacji
- 29. Czy mogę mieć RSpec bez klasy dla metod
- 30. Czy mogę utworzyć niestandardowe pole tekstowe i klawiaturę dla podklasy UIControl dla systemu iOS bez podwersji?
wiem można zdobić zajęcia z różnych XmlAttributes (jak '' XmlArray' XmlElement', itp), ale pytasz konkretnie o tym, jak sterować wyjściem XML klas niemodyfikowalne? –
Używam klas "proxy", które implikują IXmlSerializable z podaną nazwą głównego znacznika i używają funkcji ReadXml do konstruowania rzeczywistej wartości bazowej, która jest następnie eksponowana w publicznej własności. – asawyer
Cóż, istnieje przeciążenie konstruktora (http://msdn.microsoft.com/en-us/library/65k4wece.aspx), które pozwala zastąpić atrybuty używane w typach, ale nie wiem, czy to pozwala zmienić zachowanie/wynik 'IXmlSerializable.ReadXml'. EDYCJA: Czy można oddzielić obawy związane z serializacją między obiektami biznesowymi a obiektami stron trzecich? –