using System.Collections.Generic;
using System.Xml.Serialization;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO.Compression;
using Polenter.Serialization;
using Polenter.Serialization.Advanced;
using Polenter.Serialization.Core;
using Polenter.Serialization.Advanced.Deserializing;
using Polenter.Serialization.Advanced.Serializing;
public List<Model> Models { get; set; } = new ();
public string Value { get; set; }
[SharpSerializerIgnoreForDeserialize]
public string IgnoreMe { get; set; }
[System.AttributeUsage(System.AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class SharpSerializerIgnoreForDeserializeAttribute : System.Attribute { }
public class PropertyDeserializerDecorator : IPropertyDeserializer
readonly IPropertyDeserializer deserializer;
public PropertyDeserializerDecorator(IPropertyDeserializer deserializer) => this.deserializer = deserializer ?? throw new ArgumentNullException();
public virtual void Open(Stream stream) => deserializer.Open(stream);
public virtual Property Deserialize() => deserializer.Deserialize();
public virtual void Close() => deserializer.Close();
public class CustomPropertyDeserializer : PropertyDeserializerDecorator
Action<Property> deserializePropertyAction;
public CustomPropertyDeserializer(IPropertyDeserializer deserializer, Action<Property> deserializePropertyAction = default) : base(deserializer) => this.deserializePropertyAction = deserializePropertyAction;
public override Property Deserialize()
var property = base.Deserialize();
if (deserializePropertyAction != null)
property.WalkProperties(p => deserializePropertyAction(p));
public static partial class SharpSerializerExtensions
public static SharpSerializer Create(SharpSerializerXmlSettings settings, Action<Property> deserializePropertyAction = default)
var typeNameConverter = settings.AdvancedSettings.TypeNameConverter ??
settings.IncludeAssemblyVersionInTypeName,
settings.IncludeCultureInTypeName,
settings.IncludePublicKeyTokenInTypeName);
var simpleValueConverter = settings.AdvancedSettings.SimpleValueConverter ?? new SimpleValueConverter(settings.Culture, typeNameConverter);
var xmlWriterSettings = new XmlWriterSettings
Encoding = settings.Encoding,
OmitXmlDeclaration = true,
var xmlReaderSettings = new XmlReaderSettings
var reader = new DefaultXmlReader(typeNameConverter, simpleValueConverter, xmlReaderSettings);
var writer = new DefaultXmlWriter(typeNameConverter, simpleValueConverter, xmlWriterSettings);
var _serializer = new XmlPropertySerializer(writer);
var _deserializer = new CustomPropertyDeserializer(new XmlPropertyDeserializer(reader), deserializePropertyAction);
var serializer = new SharpSerializer(_serializer, _deserializer)
RootName = settings.AdvancedSettings.RootName,
serializer.PropertyProvider.PropertiesToIgnore = settings.AdvancedSettings.PropertiesToIgnore;
serializer.PropertyProvider.AttributesToIgnore = settings.AdvancedSettings.AttributesToIgnore;
public static void WalkProperties(this Property property, Action<Property> action)
if (action == null || property == null)
throw new ArgumentNullException();
case PropertyArt.Collection:
foreach (var item in ((CollectionProperty)property).Items)
item.WalkProperties(action);
case PropertyArt.Complex:
foreach (var item in ((ComplexProperty)property).Properties)
item.WalkProperties(action);
case PropertyArt.Dictionary:
foreach (var item in ((DictionaryProperty)property).Items)
item.Key.WalkProperties(action);
item.Value.WalkProperties(action);
case PropertyArt.MultiDimensionalArray:
foreach (var item in ((MultiDimensionalArrayProperty )property).Items)
item.Value.WalkProperties(action);
case PropertyArt.Reference:
case PropertyArt.SingleDimensionalArray:
foreach (var item in ((SingleDimensionalArrayProperty)property).Items)
item.WalkProperties(action);
throw new NotImplementedException(property.Art.ToString());
public static void RemoveIgnoredChildProperties(Property p)
if (p.Art == PropertyArt.Complex)
var items = ((ComplexProperty)p).Properties;
for (int i = items.Count - 1; i >= 0; i--)
if (p.Type.GetProperty(items[i].Name)?.IsDefined(typeof(SharpSerializerIgnoreForDeserializeAttribute), true) == true)
public static void Test()
Models = { new Model { Value = "value", IgnoreMe = "Ignore Me" } },
using var stream = new MemoryStream();
var serializer = new SharpSerializer();
serializer.Serialize(test, stream);
using (var reader = new StreamReader(stream, leaveOpen : true))
xml = reader.ReadToEnd();
Assert.IsTrue(xml.Contains("Ignore Me"));
var settings = new SharpSerializerXmlSettings();
var customSerialzier = SharpSerializerExtensions.Create(settings, SharpSerializerExtensions.RemoveIgnoredChildProperties);
var deserialized = (Root)customSerialzier.Deserialize(stream);
Assert.IsTrue(deserialized.Models.All(m => m.IgnoreMe == null));
public static void Main()
Console.WriteLine("Environment version: {0} ({1})", System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription , GetNetCoreVersion());
Console.WriteLine("{0} version: {1}", typeof(SharpSerializer).Assembly.GetName().Name, typeof(SharpSerializer).Assembly.FullName);
Console.WriteLine("Failed with unhandled exception: ");
public static string GetNetCoreVersion()
var assembly = typeof(System.Runtime.GCSettings).GetTypeInfo().Assembly;
var assemblyPath = assembly.Location.Split(new[] { '/', '\\' }, StringSplitOptions.RemoveEmptyEntries);
int netCoreAppIndex = Array.IndexOf(assemblyPath, "Microsoft.NETCore.App");
if (netCoreAppIndex > 0 && netCoreAppIndex < assemblyPath.Length - 2)
return assemblyPath[netCoreAppIndex + 1];
public class DebugPropertyDeserializerDecorator : PropertyDeserializerDecorator
public DebugPropertyDeserializerDecorator(IPropertyDeserializer deserializer) : base(deserializer) { }
public override Property Deserialize()
var property = base.Deserialize();
property.WalkProperties((p, s) =>
Console.WriteLine("{0}{1} of type {2}, parent of type {3}", new string(' ', 2*s.Count), p.Name, p.Type, p.Parent?.Type);
public class CustomPropertyProvider : PropertyProvider
protected override PropertyInfo[] GetAllProperties(Type type)
var properties = base.GetAllProperties(type);
if (type == typeof(Model))
properties = properties.Where(p => p.Name != nameof(Model.IgnoreMe)).ToArray();
Console.WriteLine(string.Join(",", properties.Select(p => p.ToString())));