Click here to Skip to main content
15,892,005 members
Articles / Database Development / SQL Server / SQL Server 2008

Simple Data Access in C#

Rate me:
Please Sign up or sign in to vote.
4.11/5 (15 votes)
11 Jan 2009CPOL5 min read 83.8K   1.4K   58  
Fast and easy to use data access class library.
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Globalization;

using Yap.Data.Client.Properties;


namespace Yap.Data.Client
{
	/// <summary>
	/// Simplifies access to properties of an entity. Used by entity commands to get/set entity property values.
	/// </summary>
	public class Accessor
	{
		private static readonly Object _Sync = new Object();

		private static readonly Dictionary<Type, Accessor> _Instances
			= new Dictionary<Type, Accessor>();


		/// <summary>
		/// Returns existing or initializes new <see cref="Yap.Data.Client.Accessor"/> instance for specified entity type.
		/// </summary>
		/// <param name="entityType">The type of entity.</param>
		/// <returns>The accessor.</returns>
		/// <exception cref="System.ArgumentNullException">entityType is null.</exception>
		public static Accessor GetInstance(Type entityType)
		{
			lock (_Sync)
			{
				if (entityType == null)
				{
					throw new ArgumentNullException("entityType");
				}
				Accessor accessor;
				if (!_Instances.TryGetValue(entityType, out accessor))
				{
					accessor = new Accessor(entityType);
					_Instances.Add(entityType, accessor);
				}
				return accessor;
			}
		}

		private readonly Type _Type;

		private readonly Dictionary<String, PropertyInfo> _Properties =
			new Dictionary<String, PropertyInfo>();

		private Accessor(Type entityType)
		{
			_Type = entityType;

			PropertyInfo[] properties = _Type.GetProperties(
				BindingFlags.Instance |
				BindingFlags.Public);

			foreach (PropertyInfo property in properties)
			{
				if (!_Properties.ContainsKey(property.Name))
				{
					_Properties.Add(
						property.Name, property);
				}
			}
		}

		/// <summary>
		/// Gets collection of entity properties.
		/// </summary>
		public ICollection<PropertyInfo> Properties
		{
			get
			{
				return _Properties.Values;
			}
		}

		/// <summary>
		/// Sets value into entity property by path specified.
		/// </summary>
		/// <param name="entity">Property owner.</param>
		/// <param name="propertyPath">The property path to set value to.</param>
		/// <param name="value">The value to set.</param>
		/// <exception cref="System.InvalidOperationException">Entity property was not found by specified path.</exception>
		public void SetPropertyValue(Object entity, String propertyPath, Object value)
		{
			Int32 indexOfDelimiter = propertyPath.IndexOf('.');
			String propertyName = indexOfDelimiter > 0 ? propertyPath.Substring(0, indexOfDelimiter) : propertyPath;
			PropertyInfo property;
			if (!TryGetProperty(propertyName, out property))
			{
				throw new InvalidOperationException(
					String.Format(
						CultureInfo.CurrentCulture,
						Resources.PropertyWasNotFoundInTypeException,
						propertyName,
						_Type.Name));
			}
			if (indexOfDelimiter == -1)
			{
				property.SetValue(
					entity, value, null);
			}
			else
			{
				Type propertyType = property.PropertyType;
				Object propertyValue = GetPropertyValue(entity, propertyName) ?? Activator.CreateInstance(propertyType);
				Accessor accessor = GetInstance(propertyType);
				accessor.SetPropertyValue(
					propertyValue,
					propertyPath.Substring(
						indexOfDelimiter + 1,
						propertyPath.Length - propertyName.Length - 1),
					value);
				SetPropertyValue(entity, propertyName, propertyValue);
			}
		}

		/// <summary>
		/// Gets entity property value.
		/// </summary>
		/// <param name="entity">Property owner.</param>
		/// <param name="propertyPath">The property path to get value from.</param>
		/// <returns>The value of entity property.</returns>
		/// <exception cref="System.InvalidOperationException">Entity property was not found by specified path.</exception>
		public Object GetPropertyValue(Object entity, String propertyPath)
		{
			Int32 indexOfDelimiter = propertyPath.IndexOf('.');
			String propertyName = indexOfDelimiter > 0 ? propertyPath.Substring(0, indexOfDelimiter) : propertyPath;
			PropertyInfo property;
			if (!TryGetProperty(propertyName, out property))
			{
				throw new InvalidOperationException(
					String.Format(
						CultureInfo.CurrentCulture,
						Resources.PropertyWasNotFoundInTypeException,
						propertyName,
						_Type.Name));
			}
			if (indexOfDelimiter == -1)
			{
				return property.GetValue(
					entity, null);
			}
			
			Object propertyValue = GetPropertyValue(entity, propertyName);
			if (propertyValue == null)
			{
				return null;
			}
			Accessor accessor = GetInstance(property.PropertyType);
			return accessor.GetPropertyValue(
				propertyValue,
				propertyPath.Substring(
					indexOfDelimiter + 1,
					propertyPath.Length - propertyName.Length - 1));
		}

		/// <summary>
		/// Gets entity property <see cref="System.Reflection.PropertyInfo"/> by property path.
		/// </summary>
		/// <param name="propertyPath">The property path to get <see cref="System.Reflection.PropertyInfo"/> from.</param>
		/// <returns>The <see cref="System.Reflection.PropertyInfo"/> of entity property.</returns>
		/// <exception cref="System.InvalidOperationException">Entity property was not found by specified path.</exception>
		public PropertyInfo GetProperty(String propertyPath)
		{
			PropertyInfo property;
			if (!TryGetProperty(propertyPath, out property))
			{
				throw new InvalidOperationException(
					String.Format(
						CultureInfo.CurrentCulture,
						Resources.PropertyWasNotFoundInTypeException,
						propertyPath,
						_Type.Name));
			}
			return property;
		}

		/// <summary>
		/// Gets entity property <see cref="System.Reflection.PropertyInfo"/> by property path.
		/// </summary>
		/// <param name="propertyPath">The property path to get <see cref="System.Reflection.PropertyInfo"/> from.</param>
		/// <param name="property">When this method returns, contains the <see cref="System.Reflection.PropertyInfo"/> of entity property, if property is found; otherwise, null.</param>
		/// <returns>true if entity contains an property with specified path; otherwise, false.</returns>
		public Boolean TryGetProperty(String propertyPath, out PropertyInfo property)
		{
			Int32 indexOfDelimiter = propertyPath.IndexOf('.');
			String propertyName = indexOfDelimiter > 0 ? propertyPath.Substring(0, indexOfDelimiter) : propertyPath;

			if (_Properties.TryGetValue(propertyName, out property))
			{
				if (indexOfDelimiter == -1)
				{
					return property != null;
				}
				Accessor accessor = GetInstance(property.PropertyType);
				return accessor.TryGetProperty(
					propertyPath.Substring(
						indexOfDelimiter + 1,
						propertyPath.Length - propertyName.Length - 1),
					out property);
			}
			return false;
		}
	}
}

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
Russian Federation Russian Federation
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions