Click here to Skip to main content
15,881,881 members
Articles / Programming Languages / C#

UniversalSerializer

Rate me:
Please Sign up or sign in to vote.
4.97/5 (108 votes)
15 Apr 2018Ms-RL31 min read 256.9K   4K   299  
An universal and easy serialization library for .NET and .NET Core.

// Copyright Christophe Bertrand.

using System;
using System.Collections.Generic;
using System.Windows.Markup;

namespace UniversalSerializerLib2
{
	/// <summary>
	/// For classes with [ValueSerializer].
	/// </summary>
	internal class XAMLValueSerializerContainer : ITypeContainer
	{
		static Dictionary<Type, ValueSerializer> VSCache = new Dictionary<Type, ValueSerializer>();

		public XAMLValueSerializerContainer()
		{ }

		public object Deserialize()
		{
			throw new NotSupportedException();
		}

		static ValueSerializer GetValueSerializerByCache(Type t)
		{
			ValueSerializer vs;
			if (XAMLValueSerializerContainer.VSCache.TryGetValue(t, out vs))
				return vs;
			var c = t.GetCustomAttributes(typeof(ValueSerializerAttribute), true);
			ValueSerializerAttribute att = c[0] as ValueSerializerAttribute;
			vs = System.Activator.CreateInstance(att.ValueSerializerType) as ValueSerializer;
			XAMLValueSerializerContainer.VSCache.Add(t, vs);
			return vs;
		}

		public bool IsValidType(System.Type type)
		{
			bool ret;
			if (!IsValidTypeCache.TryGetValue(type, out ret))
			{
				ret = this._IsValidType(type);
				IsValidTypeCache.Add(type, ret);
			}
			return ret;
		}
		static Dictionary<Type, bool> IsValidTypeCache = new Dictionary<Type, bool>();
		bool _IsValidType(Type type)
		{
			return (type.GetCustomAttributes(typeof(System.Windows.Markup.ValueSerializerAttribute), true).Length > 0)
				// warning: some classes do not transcode the values. e.g. LinearGradientBrush do not.
			&& (!Tools.TypeIs(type, tLinearGradientBrush));
		}
		static readonly Type tLinearGradientBrush = Tools.GetTypeFromFullName("System.Windows.Media.LinearGradientBrush");

		public ITypeContainer CreateNewContainer(object ContainedObject)
		{
			if (ContainedObject == null)
				return null;

			Type type = ContainedObject.GetType();
			ITypeContainer obj = null;

			var vs = GetValueSerializerByCache(type);
			{
				obj = CreateAValueSerializerContainerGeneric(type, vs.ConvertToString(ContainedObject, null));
			}
			if (obj == null)
				throw new Exception(string.Format("The type '{0}' uses {1} as ValueSerializer, but it was not transcoded correctly. Please investigate or contact the author.", type.FullName, vs.GetType().FullName));

			return obj;
		}

		static ITypeContainer CreateAValueSerializerContainerGeneric(
			Type SourceObjectType, string SerializedObject)
		{
			Type g;
			if (!GenericContainersTypeCache.TryGetValue(SourceObjectType, out g))
			{
				Type[] typeArgs = { SourceObjectType };
				g = GenericType.MakeGenericType(typeArgs);
				GenericContainersTypeCache.Add(SourceObjectType, g);
			}
			object o = Activator.CreateInstance(g, SerializedObject);
			return o as ITypeContainer;
		}
		static Type GenericType = typeof(XAMLValueSerializerContainerGeneric<>);
		static Dictionary<Type, Type> GenericContainersTypeCache
			= new Dictionary<Type, Type>();
		static string SerializeObject(object o)
		{
			ValueSerializer serialiseur = XAMLValueSerializerContainer.GetValueSerializerByCache(o.GetType());
			return serialiseur.ConvertToString(o, null);
		}

		public bool ApplyEvenIfThereIsAValidConstructor
		{
			get { return true; }
		}

		// ----------------------------------------------------------------------------------
		// ###########################

		/// <summary>
		/// Internal generic adaptation.
		/// For classes with [ValueSerializer].
		/// </summary>
		internal class XAMLValueSerializerContainerGeneric<TSourceObject> : ITypeContainer
		{
			public string StringSerialized;

			public XAMLValueSerializerContainerGeneric()
			{ }

			public XAMLValueSerializerContainerGeneric(string Serialized)
			{
				this.StringSerialized = Serialized;
			}

			public object Deserialize()
			{
				ValueSerializer serialiseur = XAMLValueSerializerContainer.GetValueSerializerByCache(typeof(TSourceObject));
				return serialiseur.ConvertFromString(this.StringSerialized, null);
			}

			static string SerializeObject(object o)
			{
				throw new NotSupportedException();
			}

			public bool IsValidType(Type type)
			{
				throw new NotSupportedException();
			}

			public ITypeContainer CreateNewContainer(object ContainedObject)
			{
				throw new NotSupportedException();
			}

			public bool ApplyEvenIfThereIsAValidConstructor
			{
				get
				{
					throw new NotSupportedException();
				}
			}

			public bool ApplyToStructures
			{
				get { throw new NotImplementedException(); }
			}
		}

		public bool ApplyToStructures
		{
			get { return true; }
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under Microsoft Reciprocal License


Written By
Software Developer (Senior) independent
France France
Hi !

I made my first program on a Sinclair ZX-81.
Since that day, I have the virus of computers. Smile | :)

Here is my website:
https://chrisbertrand.net

And my blog:
https://chrisbertrandprogramer.wordpress.com/

Comments and Discussions