Click here to Skip to main content
15,896,063 members
Articles / Hosted Services / Azure

Kerosene ORM: a dynamic, configuration-less and self-adaptive ORM for POCO objects supporting a SQL-like syntax from C#

Rate me:
Please Sign up or sign in to vote.
4.96/5 (71 votes)
1 Mar 2015CPOL35 min read 548.5K   4.6K   212  
The seventh version of the dynamic, configuration-less and self-adaptive Kerosene ORM library, that provides full real support for POCO objects, natural SQL-like syntax from C#, and advanced capabilities while being extremely easy to use.
// ======================================================== Parameter.cs
namespace Kerosene.ORM.Core.Concrete
{
	using Kerosene.Tools;
	using System;
	using System.Collections;
	using System.Collections.Generic;
	using System.Linq;
	using System.Runtime.Serialization;
	using System.Text;

	// ==================================================== 
	/// <summary>
	/// Represents a parameter of a command in an agnostic database-independent way.
	/// </summary>
	[Serializable]
	public class Parameter : IParameter
	{
		bool _IsDisposed = false;
		IParameterCollection _Owner = null;
		string _Name = null;
		object _Value = null;

		/// <summary>
		/// Initializes a new instance.
		/// </summary>
		public Parameter() { }

		/// <summary>
		/// Whether this instance has been disposed or not.
		/// </summary>
		public bool IsDisposed
		{
			get { return _IsDisposed; }
		}

		/// <summary>
		/// Disposes this instance.
		/// </summary>
		public void Dispose()
		{
			if (!IsDisposed) { OnDispose(true); GC.SuppressFinalize(this); }
		}

		~Parameter()
		{
			if (!IsDisposed) OnDispose(false);
		}

		/// <summary>
		/// Invoked when disposing or finalizing this instance.
		/// </summary>
		/// <param name="disposing">True if the object is being disposed, false otherwise.</param>
		protected virtual void OnDispose(bool disposing)
		{
			if (disposing)
			{
				if (_Owner != null)
				{
					var temp = _Owner; _Owner = null;
					if (temp != null && !temp.IsDisposed) temp.Remove(this);
				}
			}
			_Owner = null;
			_Value = _Value.Sketch();

			_IsDisposed = true;
		}

		/// <summary>
		/// Returns the string representation of this instance.
		/// </summary>
		/// <returns>A string containing the standard representation of this instance.</returns>
		public override string ToString()
		{
			var str = string.Format("{0} = '{1}'",
				Name ?? string.Empty,
				Value.Sketch());

			return IsDisposed ? string.Format("disposed::{0}({1})", GetType().EasyName(), str) : str;
		}

		/// <summary>
		/// Call-back method required for custom serialization.
		/// </summary>
		public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
		{
			if (IsDisposed) throw new ObjectDisposedException(this.ToString());

			info.AddValue("Name", _Name);
			info.AddExtended("Value", _Value);
		}

		/// <summary>
		/// Protected initializer required for custom serialization.
		/// </summary>
		protected Parameter(SerializationInfo info, StreamingContext context)
		{
			_Name = info.GetString("Name");
			_Value = info.GetExtended("Value");
		}

		/// <summary>
		/// Returns a new instance that is a copy of the original one.
		/// </summary>
		/// <returns>A new instance.</returns>
		public Parameter Clone()
		{
			var cloned = new Parameter();
			OnClone(cloned); return cloned;
		}
		IParameter IParameter.Clone()
		{
			return this.Clone();
		}
		object ICloneable.Clone()
		{
			return this.Clone();
		}

		/// <summary>
		/// Invoked when cloning this object to set its state at this point of the inheritance
		/// chain.
		/// </summary>
		/// <param name="cloned">The cloned object.</param>
		protected virtual void OnClone(object cloned)
		{
			if (IsDisposed) throw new ObjectDisposedException(this.ToString());
			var temp = cloned as Parameter;
			if (cloned == null) throw new InvalidCastException(
				"Cloned instance '{0}' is not a valid '{1}' one."
				.FormatWith(cloned.Sketch(), typeof(Parameter).EasyName()));

			temp.Name = Name;
			temp.Value = Value.TryClone();
		}

		/// <summary>
		/// Returns true if this object can be considered as equivalent to the target one given.
		/// </summary>
		/// <param name="target">The target object this one will be tested for equivalence.</param>
		/// <returns>True if this object can be considered as equivalent to the target one given.</returns>
		public bool EquivalentTo(IParameter target)
		{
			return OnEquivalentTo(target);
		}

		/// <summary>
		/// Invoked to test equivalence at this point of the inheritance chain.
		/// </summary>
		/// <param name="target">The target this instance will be tested for equivalence against.</param>
		/// <returns>True if at this level on the inheritance chain this instance can be considered
		/// equivalent to the target instance given.</returns>
		protected virtual bool OnEquivalentTo(object target)
		{
			if (object.ReferenceEquals(this, target)) return true;
			var temp = target as IParameter; if (temp == null) return false;
			if (temp.IsDisposed) return false;
			if (IsDisposed) return false;

			bool thiscs = this.Owner == null ? Core.ParameterCollection.DEFAULT_CASE_SENSITIVE_NAMES : this.Owner.CaseSensitiveNames;
			bool othercs = temp.Owner == null ? Core.ParameterCollection.DEFAULT_CASE_SENSITIVE_NAMES : temp.Owner.CaseSensitiveNames;
			if (thiscs != othercs) return false;

			if (string.Compare(this.Name, temp.Name, !thiscs) != 0) return false;
			if (!Value.IsEquivalentTo(temp.Value)) return false;

			return true;
		}

		/// <summary>
		/// The collection this instance belongs to, if any.
		/// </summary>
		public IParameterCollection Owner
		{
			get { return _Owner; }
			set
			{
				if (value == null)
				{
					var temp = _Owner; _Owner = null;
					if (temp != null && !temp.IsDisposed) temp.Remove(this);
				}
				else
				{
					if (IsDisposed) throw new ObjectDisposedException(this.ToString());

					if (object.ReferenceEquals(value, _Owner)) return;
					if (_Owner != null) throw new NotOrphanException(
						"This '{0}' is not an orphan one.".FormatWith(this));

					// To intercept the re-entrant operation...
					if (!value.Contains(this)) value.Add(this);
					_Owner = value;
				}
			}
		}

		/// <summary>
		/// The name of this command as it will be represented when used in a command against
		/// an underlying database.
		/// </summary>
		public string Name
		{
			get { return _Name; }
			set
			{
				if (IsDisposed) throw new ObjectDisposedException(this.ToString());
				if (Owner != null) throw new NotOrphanException("This '{0}' is not orphan.".FormatWith(this));

				_Name = Core.Parameter.ValidateName(value);
			}
		}

		/// <summary>
		/// The value or reference held by this instance, that when the command is executed will
		/// be converted into an appropriate value understood by the underlying database.
		/// </summary>
		/// <remarks>This property can be changed even if this instance is not an orphan one to
		/// permit an easy reutilization.</remarks>
		public object Value
		{
			get { return _Value; }
			set
			{
				if (IsDisposed) throw new ObjectDisposedException(this.ToString());
				_Value = value;
			}
		}
	}
}
// ======================================================== 

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 The Code Project Open License (CPOL)


Written By
Spain Spain
mbarbac has worked in start-ups, multinational tech companies, and consulting ones, serving as CIO, CTO, SW Development Director, and Consulting Director, among many other roles.

Solving complex puzzles and getting out of them business value has ever been among his main interests - and that's why he has spent his latest 25 years trying to combine his degree in Theoretical Physics with his MBA... and he is still trying to figure out how all these things can fit together.

Even if flying a lot across many countries, along with the long working days that are customary in IT management and Consultancy, he can say that, after all, he lives in Spain (at least the weekends).

Comments and Discussions