Click here to Skip to main content
15,895,746 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 263.7K   4K   299  
An universal and easy serialization library for .NET and .NET Core.

// Copyright Christophe Bertrand.

using System;
using System.Collections.Generic;
using System.Collections;
using UniversalSerializerLib3.TypeManagement;

namespace UniversalSerializerLib3
{
	/// <summary>
	/// Useful functions.
	/// </summary>
	public static partial class Tools
	{

		// -------------------------------------------

		/// <summary>
		/// This class encapsulates a generic IDictionary in an object IDictionary.
		/// That simplies some code in the project.
		/// This class is NOT thread-safe nor observable.
		/// </summary>
		internal class GenericIDictionaryBoxer<TKey, TValue> : IDictionary
		{
			internal readonly IDictionary<TKey, TValue> GenericDictionary;

			public GenericIDictionaryBoxer(IDictionary<TKey, TValue> GenericDictionary)
			{
				this.GenericDictionary = GenericDictionary;
			}

			internal static IDictionary CreateFromGenericIDictionary(
				object obj, L3TypeManager typeManager)
			{
				{
					IDictionary idict = obj as IDictionary;
					if (idict != null) // example: Dictionary<,> is a IDictionary.
						return idict;
				}
				var t2 = typeof(GenericIDictionaryBoxer<,>);
				Type t = t2.MakeGenericType(new Type[] { 
					typeManager.DictionaryKeysTypeManager.l2TypeManager.L1TypeManager.type,
					typeManager.DictionaryValuesTypeManager.l2TypeManager.L1TypeManager.type }); // TODO: put this type in cache.
				return (IDictionary)Activator.CreateInstance(t, new object[] { obj });
			}

			#region IDictionary
			public void Add(object key, object value)
			{
				this.GenericDictionary.Add((TKey)key, (TValue)value);
			}

			public void Clear()
			{
				this.GenericDictionary.Clear();
			}

			public bool Contains(object key)
			{
				return this.GenericDictionary.ContainsKey((TKey)key);
			}


			private class SimpleDictionaryEnumerator : IDictionaryEnumerator
			{
				readonly IEnumerator<KeyValuePair<TKey,TValue>> GenericDictEnumerator;
				readonly int sourceLength;
				Int32 index = -1;

				public SimpleDictionaryEnumerator(GenericIDictionaryBoxer<TKey, TValue> sd)
				{
					this.GenericDictEnumerator = sd.GenericDictionary.GetEnumerator();
					this.sourceLength = sd.Count;
				}

				// Return the current item.
				public Object Current { get { 
					return this.CurrentDictionaryEntry();			}				}

				// Return the current item.
				DictionaryEntry CurrentDictionaryEntry()
				{
					ValidateIndex();
					KeyValuePair<TKey, TValue> item = this.GenericDictEnumerator.Current;
					return new DictionaryEntry(item.Key, item.Value);
				}

				// Return the current dictionary entry.
				public DictionaryEntry Entry
				{
					get { return this.CurrentDictionaryEntry(); }
				}

				// Return the key of the current item.
				public Object Key { get { ValidateIndex();
				KeyValuePair<TKey, TValue> item = this.GenericDictEnumerator.Current;
				return item.Key;				}				}

				// Return the value of the current item.
				public Object Value { get { ValidateIndex();
				KeyValuePair<TKey, TValue> item = this.GenericDictEnumerator.Current;
				return item.Value;				}				}

				// Advance to the next item.
				public Boolean MoveNext()
				{
					bool ret = this.GenericDictEnumerator.MoveNext();
					if (ret)
						index++;
					return ret;
				}

				// Validate the enumeration index and throw an exception if the index is out of range.
				private void ValidateIndex()
				{
					if (index < 0 || index >= this.sourceLength)
						throw new InvalidOperationException("Enumerator is before or after the collection.");
				}

				// Reset the index to restart the enumeration.
				public void Reset()
				{
					index = -1;
					this.GenericDictEnumerator.Reset();
				}
			}
			public IDictionaryEnumerator GetEnumerator()
			{
				return new SimpleDictionaryEnumerator(this);
			}

			public bool IsFixedSize
			{
				get { return this.GenericDictionary.IsReadOnly; } // TODO use the new read-only dictionary interface in .Net 4.5 .
			}

			public bool IsReadOnly
			{
				get { return this.GenericDictionary.IsReadOnly; }
			}

			public ICollection Keys
			{
				get { throw new NotImplementedException(); } // useless here.
			}

			public void Remove(object key)
			{
				this.GenericDictionary.Remove((TKey)key);
			}

			public ICollection Values
			{
				get { throw new NotImplementedException(); } // useless here.
			}

			public object this[object key]
			{
				get
				{
					return this.GenericDictionary[(TKey)key];
				}
				set
				{
					this.GenericDictionary[(TKey)key] = (TValue)value;
				}
			}

			public void CopyTo(Array array, int index)
			{
				throw new NotImplementedException(); // useless here.
			}

			public int Count
			{
				get { 
					return this.GenericDictionary.Count; }
			}

			public bool IsSynchronized
			{
				get { throw new NotImplementedException(); } // useless here.
			}

			public object SyncRoot
			{
				get { return this.GenericDictionary; } // used to return the boxed dict.
			}

			IEnumerator IEnumerable.GetEnumerator()
			{
				return this.GenericDictionary.GetEnumerator();
			}
			#endregion IDictionary
		}

		// -------------------------------------------
		// -------------------------------------------

		// -------------------------------------------
		// -------------------------------------------
		// -------------------------------------------
		// -------------------------------------------
		// -------------------------------------------
		// -------------------------------------------
		// -------------------------------------------
		// -------------------------------------------
	}
}

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