diff Source/Mapping/MappingSchema.cs @ 0:f990fcb411a9

Копия текущей версии из github
author cin
date Thu, 27 Mar 2014 21:46:09 +0400
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Source/Mapping/MappingSchema.cs	Thu Mar 27 21:46:09 2014 +0400
@@ -0,0 +1,3921 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Data;
+using System.Data.Linq;
+using System.Data.SqlTypes;
+using System.Diagnostics;
+using System.Linq;
+using System.IO;
+using System.Reflection;
+using System.Diagnostics.CodeAnalysis;
+using System.Threading;
+using System.Xml;
+
+#if !SILVERLIGHT
+using System.Xml.Linq;
+#endif
+
+using BLToolkit.Common;
+using BLToolkit.Properties;
+using BLToolkit.Reflection;
+using BLToolkit.Reflection.Extension;
+using BLToolkit.Reflection.MetadataProvider;
+
+#region ReSharper disable
+// ReSharper disable SuggestUseVarKeywordEvident
+// ReSharper disable UseObjectOrCollectionInitializer
+// ReSharper disable SuggestUseVarKeywordEverywhere
+// ReSharper disable RedundantTypeArgumentsOfMethod
+#endregion
+
+using KeyValue = System.Collections.Generic.KeyValuePair<System.Type,System.Type>;
+using Convert  = BLToolkit.Common.Convert;
+
+namespace BLToolkit.Mapping
+{
+	public class MappingSchema
+	{
+		#region Constructors
+
+		public MappingSchema()
+		{
+			InitNullValues();
+		}
+
+		#endregion
+
+		#region ObjectMapper Support
+
+		private readonly Dictionary<Type,ObjectMapper> _mappers        = new Dictionary<Type,ObjectMapper>();
+		private readonly Dictionary<Type,ObjectMapper> _pendingMappers = new Dictionary<Type,ObjectMapper>();
+
+		public ObjectMapper GetObjectMapper(Type type)
+		{
+			ObjectMapper om;
+
+			lock (_mappers)
+			{
+				if (_mappers.TryGetValue(type, out om))
+					return om;
+
+				// This object mapper is initializing right now.
+				// Note that only one thread can access to _pendingMappers each time.
+				//
+				if (_pendingMappers.TryGetValue(type, out om))
+					return om;
+
+				om = CreateObjectMapper(type);
+
+				if (om == null)
+					throw new MappingException(
+						string.Format("Cannot create object mapper for the '{0}' type.", type.FullName));
+
+				_pendingMappers.Add(type, om);
+
+				try
+				{
+					om.Init(this, type);
+				}
+				finally
+				{
+					_pendingMappers.Remove(type);
+				}
+
+				// Officially publish this ready to use object mapper.
+				//
+				SetObjectMapperInternal(type, om);
+
+				return om;
+			}
+		}
+
+		private void SetObjectMapperInternal(Type type, ObjectMapper om)
+		{
+			_mappers.Add(type, om);
+
+			if (type.IsAbstract)
+			{
+				var actualType = TypeAccessor.GetAccessor(type).Type;
+
+				if (!_mappers.ContainsKey(actualType))
+					_mappers.Add(actualType, om);
+			}
+		}
+
+		public void SetObjectMapper(Type type, ObjectMapper om)
+		{
+			if (type == null) throw new ArgumentNullException("type");
+
+			lock (_mappers)
+				SetObjectMapperInternal(type, om);
+		}
+
+		protected virtual ObjectMapper CreateObjectMapper(Type type)
+		{
+			Attribute attr = TypeHelper.GetFirstAttribute(type, typeof(ObjectMapperAttribute));
+			return attr == null? CreateObjectMapperInstance(type): ((ObjectMapperAttribute)attr).ObjectMapper;
+		}
+
+		protected virtual ObjectMapper CreateObjectMapperInstance(Type type)
+		{
+			return new ObjectMapper();
+		}
+
+		#endregion
+
+		#region MetadataProvider
+
+		private MetadataProviderBase _metadataProvider;
+		public  MetadataProviderBase  MetadataProvider
+		{
+			[DebuggerStepThrough]
+			get { return _metadataProvider ?? (_metadataProvider = CreateMetadataProvider()); }
+			set { _metadataProvider = value; }
+		}
+
+		protected virtual MetadataProviderBase CreateMetadataProvider()
+		{
+			return MetadataProviderBase.CreateProvider();
+		}
+
+		#endregion
+
+		#region Public Members
+
+		public virtual ExtensionList Extensions { get; set; }
+
+		#endregion
+
+		#region Convert
+
+		public virtual void InitNullValues()
+		{
+			DefaultSByteNullValue          = (SByte)         GetNullValue(typeof(SByte));
+			DefaultInt16NullValue          = (Int16)         GetNullValue(typeof(Int16));
+			DefaultInt32NullValue          = (Int32)         GetNullValue(typeof(Int32));
+			DefaultInt64NullValue          = (Int64)         GetNullValue(typeof(Int64));
+			DefaultByteNullValue           = (Byte)          GetNullValue(typeof(Byte));
+			DefaultUInt16NullValue         = (UInt16)        GetNullValue(typeof(UInt16));
+			DefaultUInt32NullValue         = (UInt32)        GetNullValue(typeof(UInt32));
+			DefaultUInt64NullValue         = (UInt64)        GetNullValue(typeof(UInt64));
+			DefaultCharNullValue           = (Char)          GetNullValue(typeof(Char));
+			DefaultSingleNullValue         = (Single)        GetNullValue(typeof(Single));
+			DefaultDoubleNullValue         = (Double)        GetNullValue(typeof(Double));
+			DefaultBooleanNullValue        = (Boolean)       GetNullValue(typeof(Boolean));
+
+			DefaultStringNullValue         = (String)        GetNullValue(typeof(String));
+			DefaultDateTimeNullValue       = (DateTime)      GetNullValue(typeof(DateTime));
+			DefaultDateTimeOffsetNullValue = (DateTimeOffset)GetNullValue(typeof(DateTimeOffset));
+			DefaultLinqBinaryNullValue     = (Binary)        GetNullValue(typeof(Binary));
+			DefaultDecimalNullValue        = (Decimal)       GetNullValue(typeof(Decimal));
+			DefaultGuidNullValue           = (Guid)          GetNullValue(typeof(Guid));
+			DefaultStreamNullValue         = (Stream)        GetNullValue(typeof(Stream));
+#if !SILVERLIGHT
+			DefaultXmlReaderNullValue      = (XmlReader)     GetNullValue(typeof(XmlReader));
+			DefaultXmlDocumentNullValue    = (XmlDocument)   GetNullValue(typeof(XmlDocument));
+            DefaultXElementNullValue       = (XElement)      GetNullValue(typeof(XElement));
+#endif
+		}
+
+		#region Primitive Types
+
+		[CLSCompliant(false)]
+		public sbyte DefaultSByteNullValue { get; set; }
+
+		[CLSCompliant(false)]
+		public virtual SByte ConvertToSByte(object value)
+		{
+			return
+				value is SByte ? (SByte)value :
+				value is Byte ? (SByte)(Byte)value :
+				value == null ? DefaultSByteNullValue :
+					Convert.ToSByte(value);
+		}
+
+		public short DefaultInt16NullValue { get; set; }
+
+		public virtual Int16 ConvertToInt16(object value)
+		{
+			return
+				value is Int16? (Int16)value:
+				value == null || value is DBNull? DefaultInt16NullValue:
+					Convert.ToInt16(value);
+		}
+
+		public int DefaultInt32NullValue { get; set; }
+
+		public virtual Int32 ConvertToInt32(object value)
+		{
+			return
+				value is Int32? (Int32)value:
+				value == null || value is DBNull? DefaultInt32NullValue:
+					Convert.ToInt32(value);
+		}
+
+		public long DefaultInt64NullValue { get; set; }
+
+		public virtual Int64 ConvertToInt64(object value)
+		{
+			return
+				value is Int64? (Int64)value:
+				value == null || value is DBNull? DefaultInt64NullValue:
+					Convert.ToInt64(value);
+		}
+
+		public byte DefaultByteNullValue { get; set; }
+
+		public virtual Byte ConvertToByte(object value)
+		{
+			return
+				value is Byte? (Byte)value:
+				value == null || value is DBNull? DefaultByteNullValue:
+					Convert.ToByte(value);
+		}
+
+		[CLSCompliant(false)]
+		public ushort DefaultUInt16NullValue { get; set; }
+
+		[CLSCompliant(false)]
+		public virtual UInt16 ConvertToUInt16(object value)
+		{
+			return
+				value is UInt16? (UInt16)value:
+				value is Int16? (UInt16)(Int16)value:
+				value == null || value is DBNull? DefaultUInt16NullValue:
+					Convert.ToUInt16(value);
+		}
+
+		[CLSCompliant(false)]
+		public uint DefaultUInt32NullValue { get; set; }
+
+		[CLSCompliant(false)]
+		public virtual UInt32 ConvertToUInt32(object value)
+		{
+			return
+				value is UInt32? (UInt32)value:
+				value is Int32? (UInt32)(Int32)value:
+				value == null || value is DBNull? DefaultUInt32NullValue:
+					Convert.ToUInt32(value);
+		}
+
+		[CLSCompliant(false)]
+		public ulong DefaultUInt64NullValue { get; set; }
+
+		[CLSCompliant(false)]
+		public virtual UInt64 ConvertToUInt64(object value)
+		{
+			return
+				value is UInt64? (UInt64)value:
+				value is Int64? (UInt64)(Int64)value:
+				value == null || value is DBNull? DefaultUInt64NullValue:
+					Convert.ToUInt64(value);
+		}
+
+		public char DefaultCharNullValue { get; set; }
+
+		public virtual Char ConvertToChar(object value)
+		{
+			return
+				value is Char? (Char)value:
+				value == null || value is DBNull? DefaultCharNullValue:
+					Convert.ToChar(value);
+		}
+
+		public float DefaultSingleNullValue { get; set; }
+
+		public virtual Single ConvertToSingle(object value)
+		{
+			return
+				value is Single? (Single)value:
+				value == null || value is DBNull? DefaultSingleNullValue:
+					Convert.ToSingle(value);
+		}
+
+		public double DefaultDoubleNullValue { get; set; }
+
+		public virtual Double ConvertToDouble(object value)
+		{
+			return
+				value is Double? (Double)value:
+				value == null || value is DBNull? DefaultDoubleNullValue:
+					Convert.ToDouble(value);
+		}
+
+		public bool DefaultBooleanNullValue { get; set; }
+
+		public virtual Boolean ConvertToBoolean(object value)
+		{
+			return
+				value is Boolean? (Boolean)value:
+				value == null || value is DBNull? DefaultBooleanNullValue:
+					Convert.ToBoolean(value);
+		}
+
+		#endregion
+
+		#region Simple Types
+
+		public string DefaultStringNullValue { get; set; }
+
+		public virtual String ConvertToString(object value)
+		{
+			return
+				value is String? (String)value :
+				value == null || value is DBNull? DefaultStringNullValue:
+					Convert.ToString(value);
+		}
+
+		public DateTime DefaultDateTimeNullValue { get; set; }
+
+		public virtual DateTime ConvertToDateTime(object value)
+		{
+			return
+				value is DateTime? (DateTime)value:
+				value == null || value is DBNull? DefaultDateTimeNullValue:
+					Convert.ToDateTime(value);
+		}
+
+		public virtual TimeSpan ConvertToTimeSpan(object value)
+		{
+			return ConvertToDateTime(value).TimeOfDay;
+		}
+
+		public DateTimeOffset DefaultDateTimeOffsetNullValue { get; set; }
+
+		public virtual DateTimeOffset ConvertToDateTimeOffset(object value)
+		{
+			return
+				value is DateTimeOffset? (DateTimeOffset)value:
+				value == null || value is DBNull? DefaultDateTimeOffsetNullValue:
+					Convert.ToDateTimeOffset(value);
+		}
+
+		public Binary DefaultLinqBinaryNullValue { get; set; }
+
+		public virtual Binary ConvertToLinqBinary(object value)
+		{
+			return
+				value is Binary ? (Binary)value:
+				value is byte[] ? new Binary((byte[])value) : 
+				value == null || value is DBNull? DefaultLinqBinaryNullValue:
+					Convert.ToLinqBinary(value);
+		}
+
+		public decimal DefaultDecimalNullValue { get; set; }
+
+		public virtual Decimal ConvertToDecimal(object value)
+		{
+			return
+				value is Decimal? (Decimal)value:
+				value == null || value is DBNull? DefaultDecimalNullValue:
+					Convert.ToDecimal(value);
+		}
+
+		public Guid DefaultGuidNullValue { get; set; }
+
+		public virtual Guid ConvertToGuid(object value)
+		{
+			return
+				value is Guid? (Guid)value:
+				value == null || value is DBNull? DefaultGuidNullValue:
+					Convert.ToGuid(value);
+		}
+
+		public Stream DefaultStreamNullValue { get; set; }
+
+		public virtual Stream ConvertToStream(object value)
+		{
+			return
+				value is Stream? (Stream)value:
+				value == null || value is DBNull? DefaultStreamNullValue:
+					 Convert.ToStream(value);
+		}
+
+#if !SILVERLIGHT
+
+		public XmlReader DefaultXmlReaderNullValue { get; set; }
+
+		public virtual XmlReader ConvertToXmlReader(object value)
+		{
+			return
+				value is XmlReader? (XmlReader)value:
+				value == null || value is DBNull? DefaultXmlReaderNullValue:
+					Convert.ToXmlReader(value);
+		}
+
+		public XmlDocument DefaultXmlDocumentNullValue { get; set; }
+
+		public virtual XmlDocument ConvertToXmlDocument(object value)
+		{
+			return
+				value is XmlDocument? (XmlDocument)value:
+				value == null || value is DBNull? DefaultXmlDocumentNullValue:
+					Convert.ToXmlDocument(value);
+		}
+
+        public XElement DefaultXElementNullValue { get; set; }
+
+        public virtual XElement ConvertToXElement(object value)
+        {
+            return
+                value is XElement ? (XElement)value :
+                value == null || value is DBNull ? DefaultXElementNullValue :
+                    XElement.Parse(value.ToString());
+        }
+
+#endif
+
+		public virtual byte[] ConvertToByteArray(object value)
+		{
+			return
+				value is byte[]? (byte[])value:
+				value == null || value is DBNull? null:
+					Convert.ToByteArray(value);
+		}
+
+		public virtual char[] ConvertToCharArray(object value)
+		{
+			return
+				value is char[]? (char[])value:
+				value == null || value is DBNull? null:
+					Convert.ToCharArray(value);
+		}
+
+		#endregion
+
+		#region Nullable Types
+
+		[CLSCompliant(false)]
+		public virtual SByte? ConvertToNullableSByte(object value)
+		{
+			return
+				value is SByte? (SByte?)value:
+				value is Byte? (SByte?)(Byte)value:
+				value == null || value is DBNull? null:
+					Convert.ToNullableSByte(value);
+		}
+
+		public virtual Int16? ConvertToNullableInt16(object value)
+		{
+			return
+				value is Int16? (Int16?)value:
+				value == null || value is DBNull? null:
+					Convert.ToNullableInt16(value);
+		}
+
+		public virtual Int32? ConvertToNullableInt32(object value)
+		{
+			return
+				value is Int32? (Int32?)value:
+				value == null || value is DBNull? null:
+					Convert.ToNullableInt32(value);
+		}
+
+		public virtual Int64? ConvertToNullableInt64(object value)
+		{
+			return
+				value is Int64? (Int64?)value:
+				value == null || value is DBNull? null:
+					Convert.ToNullableInt64(value);
+		}
+
+		public virtual Byte? ConvertToNullableByte(object value)
+		{
+			return
+				value is Byte? (Byte?)value:
+				value == null || value is DBNull? null:
+					Convert.ToNullableByte(value);
+		}
+
+		[CLSCompliant(false)]
+		public virtual UInt16? ConvertToNullableUInt16(object value)
+		{
+			return
+				value is UInt16? (UInt16?)value:
+				value is Int16? (UInt16?)(Int16)value:
+				value == null || value is DBNull? null:
+					Convert.ToNullableUInt16(value);
+		}
+
+		[CLSCompliant(false)]
+		public virtual UInt32? ConvertToNullableUInt32(object value)
+		{
+			return
+				value is UInt32? (UInt32?)value:
+				value is Int32? (UInt32?)(Int32)value:
+				value == null || value is DBNull? null:
+					Convert.ToNullableUInt32(value);
+		}
+
+		[CLSCompliant(false)]
+		public virtual UInt64? ConvertToNullableUInt64(object value)
+		{
+			return
+				value is UInt64? (UInt64?)value:
+				value is Int64? (UInt64?)(Int64)value:
+				value == null || value is DBNull? null:
+					Convert.ToNullableUInt64(value);
+		}
+
+		public virtual Char? ConvertToNullableChar(object value)
+		{
+			return
+				value is Char? (Char?)value:
+				value == null || value is DBNull? null:
+					Convert.ToNullableChar(value);
+		}
+
+		public virtual Double? ConvertToNullableDouble(object value)
+		{
+			return
+				value is Double? (Double?)value:
+				value == null || value is DBNull? null:
+					Convert.ToNullableDouble(value);
+		}
+
+		public virtual Single? ConvertToNullableSingle(object value)
+		{
+			return
+				value is Single? (Single?)value:
+				value == null || value is DBNull? null:
+					Convert.ToNullableSingle(value);
+		}
+
+		public virtual Boolean? ConvertToNullableBoolean(object value)
+		{
+			return
+				value is Boolean? (Boolean?)value:
+				value == null || value is DBNull? null:
+					Convert.ToNullableBoolean(value);
+		}
+
+		public virtual DateTime? ConvertToNullableDateTime(object value)
+		{
+			return
+				value is DateTime? (DateTime?)value:
+				value == null || value is DBNull? null:
+					Convert.ToNullableDateTime(value);
+		}
+
+		public virtual TimeSpan? ConvertToNullableTimeSpan(object value)
+		{
+			DateTime? dt = ConvertToNullableDateTime(value);
+			return dt == null? null : (TimeSpan?)dt.Value.TimeOfDay;
+		}
+
+		public virtual DateTimeOffset? ConvertToNullableDateTimeOffset(object value)
+		{
+			return
+				value is DateTimeOffset? (DateTimeOffset?)value:
+				value == null || value is DBNull? null:
+					Convert.ToNullableDateTimeOffset(value);
+		}
+
+		public virtual Decimal? ConvertToNullableDecimal(object value)
+		{
+			return
+				value is Decimal? (Decimal?)value:
+				value == null || value is DBNull? null:
+					Convert.ToNullableDecimal(value);
+		}
+
+		public virtual Guid? ConvertToNullableGuid(object value)
+		{
+			return
+				value is Guid? (Guid?)value:
+				value == null || value is DBNull? null:
+					Convert.ToNullableGuid(value);
+		}
+
+		#endregion
+
+		#region SqlTypes
+
+#if !SILVERLIGHT
+
+		public virtual SqlByte ConvertToSqlByte(object value)
+		{
+			return
+				value == null || value is DBNull? SqlByte.Null :
+				value is SqlByte? (SqlByte)value:
+					Convert.ToSqlByte(value);
+		}
+
+		public virtual SqlInt16 ConvertToSqlInt16(object value)
+		{
+			return
+				value == null || value is DBNull? SqlInt16.Null:
+				value is SqlInt16? (SqlInt16)value:
+					Convert.ToSqlInt16(value);
+		}
+
+		public virtual SqlInt32 ConvertToSqlInt32(object value)
+		{
+			return
+				value == null || value is DBNull? SqlInt32.Null:
+				value is SqlInt32? (SqlInt32)value:
+					Convert.ToSqlInt32(value);
+		}
+
+		public virtual SqlInt64 ConvertToSqlInt64(object value)
+		{
+			return
+				value == null || value is DBNull? SqlInt64.Null:
+				value is SqlInt64? (SqlInt64)value:
+					Convert.ToSqlInt64(value);
+		}
+
+		public virtual SqlSingle ConvertToSqlSingle(object value)
+		{
+			return
+				value == null || value is DBNull? SqlSingle.Null:
+				value is SqlSingle? (SqlSingle)value:
+					Convert.ToSqlSingle(value);
+		}
+
+		public virtual SqlBoolean ConvertToSqlBoolean(object value)
+		{
+			return
+				value == null || value is DBNull? SqlBoolean.Null:
+				value is SqlBoolean? (SqlBoolean)value:
+					Convert.ToSqlBoolean(value);
+		}
+
+		public virtual SqlDouble ConvertToSqlDouble(object value)
+		{
+			return
+				value == null || value is DBNull? SqlDouble.Null:
+				value is SqlDouble? (SqlDouble)value:
+					Convert.ToSqlDouble(value);
+		}
+
+		public virtual SqlDateTime ConvertToSqlDateTime(object value)
+		{
+			return
+				value == null || value is DBNull? SqlDateTime.Null:
+				value is SqlDateTime? (SqlDateTime)value:
+					Convert.ToSqlDateTime(value);
+		}
+
+		public virtual SqlDecimal ConvertToSqlDecimal(object value)
+		{
+			return
+				value == null || value is DBNull? SqlDecimal.Null:
+				value is SqlDecimal? (SqlDecimal)value:
+				value is SqlMoney?   ((SqlMoney)value).ToSqlDecimal():
+					Convert.ToSqlDecimal(value);
+		}
+
+		public virtual SqlMoney ConvertToSqlMoney(object value)
+		{
+			return
+				value == null || value is DBNull? SqlMoney.Null:
+				value is SqlMoney?   (SqlMoney)value:
+				value is SqlDecimal? ((SqlDecimal)value).ToSqlMoney():
+					Convert.ToSqlMoney(value);
+		}
+
+		public virtual SqlString ConvertToSqlString(object value)
+		{
+			return
+				value == null || value is DBNull? SqlString.Null:
+				value is SqlString? (SqlString)value:
+					Convert.ToSqlString(value);
+		}
+
+		public virtual SqlBinary ConvertToSqlBinary(object value)
+		{
+			return
+				value == null || value is DBNull? SqlBinary.Null:
+				value is SqlBinary? (SqlBinary)value:
+					Convert.ToSqlBinary(value);
+		}
+
+		public virtual SqlGuid ConvertToSqlGuid(object value)
+		{
+			return
+				value == null || value is DBNull? SqlGuid.Null:
+				value is SqlGuid? (SqlGuid)value:
+					Convert.ToSqlGuid(value);
+		}
+
+		public virtual SqlBytes ConvertToSqlBytes(object value)
+		{
+			return
+				value == null || value is DBNull? SqlBytes.Null:
+				value is SqlBytes? (SqlBytes)value:
+					Convert.ToSqlBytes(value);
+		}
+
+		public virtual SqlChars ConvertToSqlChars(object value)
+		{
+			return
+				value == null || value is DBNull? SqlChars.Null:
+				value is SqlChars? (SqlChars)value:
+					Convert.ToSqlChars(value);
+		}
+
+		public virtual SqlXml ConvertToSqlXml(object value)
+		{
+			return
+				value == null || value is DBNull? SqlXml.Null:
+				value is SqlXml? (SqlXml)value:
+					Convert.ToSqlXml(value);
+		}
+
+#endif
+
+		#endregion
+
+		#region General case
+
+		public virtual T GetDefaultNullValue<T>()
+		{
+			switch (Type.GetTypeCode(typeof(T)))
+			{
+				case TypeCode.Boolean:  return (T)(object)DefaultBooleanNullValue;
+				case TypeCode.Byte:     return (T)(object)DefaultByteNullValue;
+				case TypeCode.Char:     return (T)(object)DefaultCharNullValue;
+				case TypeCode.DateTime: return (T)(object)DefaultDateTimeNullValue;
+				case TypeCode.Decimal:  return (T)(object)DefaultDecimalNullValue;
+				case TypeCode.Double:   return (T)(object)DefaultDoubleNullValue;
+				case TypeCode.Int16:    return (T)(object)DefaultInt16NullValue;
+				case TypeCode.Int32:    return (T)(object)DefaultInt32NullValue;
+				case TypeCode.Int64:    return (T)(object)DefaultInt64NullValue;
+				case TypeCode.SByte:    return (T)(object)DefaultSByteNullValue;
+				case TypeCode.Single:   return (T)(object)DefaultSingleNullValue;
+				case TypeCode.String:   return (T)(object)DefaultStringNullValue;
+				case TypeCode.UInt16:   return (T)(object)DefaultUInt16NullValue;
+				case TypeCode.UInt32:   return (T)(object)DefaultUInt32NullValue;
+				case TypeCode.UInt64:   return (T)(object)DefaultUInt64NullValue;
+			}
+
+			if (typeof(Guid)           == typeof(T)) return (T)(object)DefaultGuidNullValue;
+			if (typeof(Stream)         == typeof(T)) return (T)(object)DefaultStreamNullValue;
+#if !SILVERLIGHT
+			if (typeof(XmlReader)      == typeof(T)) return (T)(object)DefaultXmlReaderNullValue;
+			if (typeof(XmlDocument)    == typeof(T)) return (T)(object)DefaultXmlDocumentNullValue;
+            if (typeof(XElement)       == typeof(T)) return (T)(object)DefaultXElementNullValue;
+#endif
+			if (typeof(DateTimeOffset) == typeof(T)) return (T)(object)DefaultDateTimeOffsetNullValue;
+
+			return default(T);
+		}
+
+		public virtual T ConvertTo<T,TP>(TP value)
+		{
+			return Equals(value, default(TP))?
+				GetDefaultNullValue<T>():
+				Convert<T,TP>.From(value);
+		}
+
+		public virtual object ConvertChangeType(object value, Type conversionType)
+		{
+			return ConvertChangeType(value, conversionType, TypeHelper.IsNullable(conversionType));
+		}
+
+		public virtual object ConvertChangeType(object value, Type conversionType, bool isNullable)
+		{
+			if (conversionType.IsArray)
+			{
+				if (null == value)
+					return null;
+				
+				Type srcType = value.GetType();
+
+				if (srcType == conversionType)
+					return value;
+
+				if (srcType.IsArray)
+				{
+					Type srcElementType = srcType.GetElementType();
+					Type dstElementType = conversionType.GetElementType();
+
+					if (srcElementType.IsArray != dstElementType.IsArray
+						|| (srcElementType.IsArray &&
+							srcElementType.GetArrayRank() != dstElementType.GetArrayRank()))
+					{
+						throw new InvalidCastException(string.Format(
+							Resources.MappingSchema_IncompatibleArrayTypes,
+							srcType.FullName, conversionType.FullName));
+					}
+
+					Array srcArray = (Array)value;
+					Array dstArray;
+
+					int rank = srcArray.Rank;
+
+					if (rank == 1 && 0 == srcArray.GetLowerBound(0))
+					{
+						int arrayLength = srcArray.Length;
+
+						dstArray = Array.CreateInstance(dstElementType, arrayLength);
+
+						// Int32 is assignable from UInt32, SByte from Byte and so on.
+						//
+						if (dstElementType.IsAssignableFrom(srcElementType))
+							Array.Copy(srcArray, dstArray, arrayLength);
+						else
+							for (int i = 0; i < arrayLength; ++i)
+								dstArray.SetValue(ConvertChangeType(srcArray.GetValue(i), dstElementType, isNullable), i);
+					}
+					else
+					{
+#if SILVERLIGHT
+						throw new InvalidOperationException();
+#else
+						var arrayLength = 1;
+						var dimensions  = new int[rank];
+						var indices     = new int[rank];
+						var lbounds     = new int[rank];
+
+						for (int i = 0; i < rank; ++i)
+						{
+							arrayLength *= (dimensions[i] = srcArray.GetLength(i));
+							lbounds[i] = srcArray.GetLowerBound(i);
+						}
+
+						dstArray = Array.CreateInstance(dstElementType, dimensions, lbounds);
+
+						for (int i = 0; i < arrayLength; ++i)
+						{
+							var index = i;
+
+							for (var j = rank - 1; j >= 0; --j)
+							{
+								indices[j] = index % dimensions[j] + lbounds[j];
+								index /= dimensions[j];
+							}
+
+							dstArray.SetValue(ConvertChangeType(srcArray.GetValue(indices), dstElementType, isNullable), indices);
+						}
+
+#endif
+					}
+
+					return dstArray;
+				}
+			}
+			else if (conversionType.IsEnum)
+			{
+				return MapValueToEnum(value, conversionType);
+			}
+
+			if (isNullable)
+			{
+				if (TypeHelper.IsNullable(conversionType))
+				{
+					// Return a null reference or boxed not null value.
+					//
+					return value == null || value is DBNull? null:
+						ConvertChangeType(value, conversionType.GetGenericArguments()[0]);
+				}
+
+				Type type = conversionType.IsEnum? Enum.GetUnderlyingType(conversionType): conversionType;
+
+				switch (Type.GetTypeCode(type))
+				{
+					case TypeCode.Boolean:  return ConvertToNullableBoolean (value);
+					case TypeCode.Byte:     return ConvertToNullableByte    (value);
+					case TypeCode.Char:     return ConvertToNullableChar    (value);
+					case TypeCode.DateTime: return ConvertToNullableDateTime(value);
+					case TypeCode.Decimal:  return ConvertToNullableDecimal (value);
+					case TypeCode.Double:   return ConvertToNullableDouble  (value);
+					case TypeCode.Int16:    return ConvertToNullableInt16   (value);
+					case TypeCode.Int32:    return ConvertToNullableInt32   (value);
+					case TypeCode.Int64:    return ConvertToNullableInt64   (value);
+					case TypeCode.SByte:    return ConvertToNullableSByte   (value);
+					case TypeCode.Single:   return ConvertToNullableSingle  (value);
+					case TypeCode.UInt16:   return ConvertToNullableUInt16  (value);
+					case TypeCode.UInt32:   return ConvertToNullableUInt32  (value);
+					case TypeCode.UInt64:   return ConvertToNullableUInt64  (value);
+				}
+
+				if (typeof(Guid)           == conversionType) return ConvertToNullableGuid(value);
+				if (typeof(DateTimeOffset) == conversionType) return ConvertToNullableDateTimeOffset(value);
+				if (typeof(TimeSpan)       == conversionType) return ConvertToNullableTimeSpan(value);	
+			}
+
+			switch (Type.GetTypeCode(conversionType))
+			{
+				case TypeCode.Boolean:  return ConvertToBoolean (value);
+				case TypeCode.Byte:     return ConvertToByte    (value);
+				case TypeCode.Char:     return ConvertToChar    (value);
+				case TypeCode.DateTime: return ConvertToDateTime(value);
+				case TypeCode.Decimal:  return ConvertToDecimal (value);
+				case TypeCode.Double:   return ConvertToDouble  (value);
+				case TypeCode.Int16:    return ConvertToInt16   (value);
+				case TypeCode.Int32:    return ConvertToInt32   (value);
+				case TypeCode.Int64:    return ConvertToInt64   (value);
+				case TypeCode.SByte:    return ConvertToSByte   (value);
+				case TypeCode.Single:   return ConvertToSingle  (value);
+				case TypeCode.String:   return ConvertToString  (value);
+				case TypeCode.UInt16:   return ConvertToUInt16  (value);
+				case TypeCode.UInt32:   return ConvertToUInt32  (value);
+				case TypeCode.UInt64:   return ConvertToUInt64  (value);
+			}
+
+			if (typeof(Guid)           == conversionType) return ConvertToGuid          (value);
+			if (typeof(Stream)         == conversionType) return ConvertToStream        (value);
+#if !SILVERLIGHT
+			if (typeof(XmlReader)      == conversionType) return ConvertToXmlReader     (value);
+			if (typeof(XmlDocument)    == conversionType) return ConvertToXmlDocument   (value);
+            if (typeof(XElement)       == conversionType) return ConvertToXElement      (value);
+#endif
+			if (typeof(byte[])         == conversionType) return ConvertToByteArray     (value);
+			if (typeof(Binary)         == conversionType) return ConvertToLinqBinary    (value);
+			if (typeof(DateTimeOffset) == conversionType) return ConvertToDateTimeOffset(value);
+			if (typeof(char[])         == conversionType) return ConvertToCharArray     (value);
+			if (typeof(TimeSpan)       == conversionType) return ConvertToTimeSpan      (value);
+
+#if !SILVERLIGHT
+
+			if (typeof(SqlInt32)       == conversionType) return ConvertToSqlInt32      (value);
+			if (typeof(SqlString)      == conversionType) return ConvertToSqlString     (value);
+			if (typeof(SqlDecimal)     == conversionType) return ConvertToSqlDecimal    (value);
+			if (typeof(SqlDateTime)    == conversionType) return ConvertToSqlDateTime   (value);
+			if (typeof(SqlBoolean)     == conversionType) return ConvertToSqlBoolean    (value);
+			if (typeof(SqlMoney)       == conversionType) return ConvertToSqlMoney      (value);
+			if (typeof(SqlGuid)        == conversionType) return ConvertToSqlGuid       (value);
+			if (typeof(SqlDouble)      == conversionType) return ConvertToSqlDouble     (value);
+			if (typeof(SqlByte)        == conversionType) return ConvertToSqlByte       (value);
+			if (typeof(SqlInt16)       == conversionType) return ConvertToSqlInt16      (value);
+			if (typeof(SqlInt64)       == conversionType) return ConvertToSqlInt64      (value);
+			if (typeof(SqlSingle)      == conversionType) return ConvertToSqlSingle     (value);
+			if (typeof(SqlBinary)      == conversionType) return ConvertToSqlBinary     (value);
+			if (typeof(SqlBytes)       == conversionType) return ConvertToSqlBytes      (value);
+			if (typeof(SqlChars)       == conversionType) return ConvertToSqlChars      (value);
+			if (typeof(SqlXml)         == conversionType) return ConvertToSqlXml        (value);
+
+#endif
+
+			return System.Convert.ChangeType(value, conversionType, Thread.CurrentThread.CurrentCulture);
+		}
+
+		#endregion
+		
+		#endregion
+
+		#region Factory Members
+
+		public virtual DataReaderMapper CreateDataReaderMapper(IDataReader dataReader)
+		{
+			return new DataReaderMapper(this, dataReader);
+		}
+
+		public virtual DataReaderListMapper CreateDataReaderListMapper(IDataReader reader)
+		{
+			return new DataReaderListMapper(CreateDataReaderMapper(reader));
+		}
+
+		public virtual DataReaderMapper CreateDataReaderMapper(
+			IDataReader          dataReader,
+			NameOrIndexParameter nameOrIndex)
+		{
+			return new ScalarDataReaderMapper(this, dataReader, nameOrIndex);
+		}
+
+		public virtual DataReaderListMapper CreateDataReaderListMapper(
+			IDataReader          reader,
+			NameOrIndexParameter nameOrIndex)
+		{
+			return new DataReaderListMapper(CreateDataReaderMapper(reader, nameOrIndex));
+		}
+
+#if !SILVERLIGHT
+
+		public virtual DataRowMapper CreateDataRowMapper(
+			DataRow        row,
+			DataRowVersion version)
+		{
+			return new DataRowMapper(row, version);
+		}
+
+		public virtual DataTableMapper CreateDataTableMapper(
+			DataTable      dataTable,
+			DataRowVersion version)
+		{
+			return new DataTableMapper(dataTable, CreateDataRowMapper(null, version));
+		}
+
+#endif
+
+		public virtual DictionaryMapper CreateDictionaryMapper(IDictionary dictionary)
+		{
+			return new DictionaryMapper(dictionary);
+		}
+
+		public virtual DictionaryListMapper CreateDictionaryListMapper(
+			IDictionary          dic,
+			NameOrIndexParameter keyFieldNameOrIndex,
+			ObjectMapper         objectMapper)
+		{
+			return new DictionaryListMapper(dic, keyFieldNameOrIndex, objectMapper);
+		}
+		
+		public virtual DictionaryIndexListMapper CreateDictionaryListMapper(
+			IDictionary  dic,
+			MapIndex     index,
+			ObjectMapper objectMapper)
+		{
+			return new DictionaryIndexListMapper(dic, index, objectMapper);
+		}
+
+		public virtual DictionaryListMapper<TK,T> CreateDictionaryListMapper<TK,T>(
+			IDictionary<TK,T>     dic,
+			NameOrIndexParameter keyFieldNameOrIndex,
+			ObjectMapper         objectMapper)
+		{
+			return new DictionaryListMapper<TK,T>(dic, keyFieldNameOrIndex, objectMapper);
+		}
+
+		public virtual DictionaryIndexListMapper<T> CreateDictionaryListMapper<T>(
+			IDictionary<CompoundValue,T> dic,
+			MapIndex                     index,
+			ObjectMapper                 objectMapper)
+		{
+			return new DictionaryIndexListMapper<T>(dic, index, objectMapper);
+		}
+
+		public virtual EnumeratorMapper CreateEnumeratorMapper(IEnumerator enumerator)
+		{
+			return new EnumeratorMapper(enumerator);
+		}
+
+		public virtual ObjectListMapper CreateObjectListMapper(IList list, ObjectMapper objectMapper)
+		{
+			return new ObjectListMapper(list, objectMapper);
+		}
+
+		public virtual ScalarListMapper CreateScalarListMapper(IList list, Type type)
+		{
+			return new ScalarListMapper(list, type);
+		}
+
+		public virtual SimpleDestinationListMapper CreateScalarDestinationListMapper(IList list, Type type)
+		{
+			return new SimpleDestinationListMapper(CreateScalarListMapper(list, type));
+		}
+
+		public virtual SimpleSourceListMapper CreateScalarSourceListMapper(IList list, Type type)
+		{
+			return new SimpleSourceListMapper(CreateScalarListMapper(list, type));
+		}
+
+		public virtual ScalarListMapper<T> CreateScalarListMapper<T>(IList<T> list)
+		{
+			return new ScalarListMapper<T>(this, list);
+		}
+
+		public virtual SimpleDestinationListMapper CreateScalarDestinationListMapper<T>(IList<T> list)
+		{
+			return new SimpleDestinationListMapper(CreateScalarListMapper<T>(list));
+		}
+
+		#endregion
+
+		#region GetNullValue
+
+		public virtual object GetNullValue(Type type)
+		{
+			return TypeAccessor.GetNullValue(type);
+		}
+
+		public virtual bool IsNull(object value)
+		{
+			return TypeAccessor.IsNull(value);
+		}
+
+		#endregion
+
+		#region GetMapValues
+
+		private readonly Dictionary<Type,MapValue[]> _mapValues = new Dictionary<Type,MapValue[]>();
+
+		public virtual MapValue[] GetMapValues([JetBrains.Annotations.NotNull] Type type)
+		{
+			if (type == null) throw new ArgumentNullException("type");
+
+			lock (_mapValues)
+			{
+				MapValue[] mapValues;
+
+				if (_mapValues.TryGetValue(type, out mapValues))
+					return mapValues;
+
+				var  typeExt = TypeExtension.GetTypeExtension(type, Extensions);
+				bool isSet;
+
+				mapValues = MetadataProvider.GetMapValues(typeExt, type, out isSet);
+
+				_mapValues.Add(type, mapValues);
+
+				return mapValues;
+			}
+		}
+
+		private readonly Dictionary<MemberAccessor, MapValue[]> _memberMapValues = new Dictionary<MemberAccessor, MapValue[]>();
+
+		private Type GetMapValueType(MapValue[] mapValues)
+		{
+			if (mapValues != null)
+			{
+				var value = mapValues.SelectMany(mv => mv.MapValues).FirstOrDefault();
+				if (value != null)
+				{
+					return value.GetType();
+				}
+			}
+			return null;
+		}
+
+		public virtual MapValue[] GetMapValues([JetBrains.Annotations.NotNull] MemberAccessor memberAccessor)
+		{
+			if (memberAccessor == null) throw new ArgumentNullException("memberAccessor");
+
+			lock (_memberMapValues)
+			{
+				MapValue[] mapValues;
+
+				if (_memberMapValues.TryGetValue(memberAccessor, out mapValues))
+					return mapValues;
+
+				var typeExt = TypeExtension.GetTypeExtension(memberAccessor.Type, Extensions);
+				bool isSet;
+
+				mapValues = MetadataProvider.GetMapValues(typeExt, memberAccessor, out isSet);
+
+				_memberMapValues.Add(memberAccessor, mapValues);
+
+				return mapValues;
+			}
+		}
+
+		#endregion
+
+		#region GetDefaultValue
+
+		private readonly Dictionary<Type,object> _defaultValues = new Dictionary<Type,object>();
+
+		public virtual object GetDefaultValue([JetBrains.Annotations.NotNull] Type type)
+		{
+			if (type == null) throw new ArgumentNullException("type");
+
+			lock (_defaultValues)
+			{
+				object defaultValue;
+
+				if (_defaultValues.TryGetValue(type, out defaultValue))
+					return defaultValue;
+
+				var  typeExt = TypeExtension.GetTypeExtension(type, Extensions);
+				bool isSet;
+
+				defaultValue = MetadataProvider.GetDefaultValue(this, typeExt, type, out isSet);
+
+				_defaultValues.Add(type, defaultValue = TypeExtension.ChangeType(defaultValue, type));
+
+				return defaultValue;
+			}
+		}
+
+		#endregion
+
+		#region GetDataSource, GetDataDestination
+
+		[CLSCompliant(false)]
+		public virtual IMapDataSource GetDataSource(object obj)
+		{
+			if (obj == null) throw new ArgumentNullException("obj");
+
+			if (obj is IMapDataSource)
+				return (IMapDataSource)obj;
+
+			if (obj is IDataReader)
+				return CreateDataReaderMapper((IDataReader)obj);
+
+#if !SILVERLIGHT
+
+			if (obj is DataRow)
+				return CreateDataRowMapper((DataRow)obj, DataRowVersion.Default);
+
+			if (obj is DataRowView)
+				return CreateDataRowMapper(
+					((DataRowView)obj).Row,
+					((DataRowView)obj).RowVersion);
+
+			if (obj is DataTable)
+				return CreateDataRowMapper(((DataTable)(obj)).Rows[0], DataRowVersion.Default);
+
+#endif
+
+			if (obj is IDictionary)
+				return CreateDictionaryMapper((IDictionary)obj);
+
+			return GetObjectMapper(obj.GetType());
+		}
+
+		[CLSCompliant(false)]
+		public virtual IMapDataDestination GetDataDestination(object obj)
+		{
+			if (obj == null) throw new ArgumentNullException("obj");
+
+			if (obj is IMapDataDestination)
+				return (IMapDataDestination)obj;
+
+#if !SILVERLIGHT
+
+			if (obj is DataRow)
+				return CreateDataRowMapper((DataRow)obj, DataRowVersion.Default);
+
+			if (obj is DataRowView)
+				return CreateDataRowMapper(
+					((DataRowView)obj).Row,
+					((DataRowView)obj).RowVersion);
+
+			if (obj is DataTable)
+			{
+				DataTable dt = obj as DataTable;
+				DataRow   dr = dt.NewRow();
+
+				dt.Rows.Add(dr);
+
+				return CreateDataRowMapper(dr, DataRowVersion.Default);
+			}
+
+#endif
+
+			if (obj is IDictionary)
+				return CreateDictionaryMapper((IDictionary)obj);
+
+			return GetObjectMapper(obj.GetType());
+		}
+
+		[CLSCompliant(false)]
+		public virtual IMapDataSourceList GetDataSourceList(object obj)
+		{
+			if (obj == null) throw new ArgumentNullException("obj");
+
+			if (obj is IMapDataSourceList)
+				return (IMapDataSourceList)obj;
+
+			if (obj is IDataReader)
+				return CreateDataReaderListMapper((IDataReader)obj);
+
+			Type type = obj.GetType().GetElementType();
+
+			return TypeHelper.IsScalar(type)?
+				(IMapDataSourceList)CreateScalarSourceListMapper((IList)obj, type):
+				CreateObjectListMapper((IList)obj, CreateObjectMapper(type));
+		}
+
+		[CLSCompliant(false)]
+		public virtual IMapDataDestinationList GetDataDestinationList(object obj)
+		{
+			if (obj == null) throw new ArgumentNullException("obj");
+
+			if (obj is IMapDataDestinationList)
+				return (IMapDataDestinationList)obj;
+
+			Type type = obj.GetType().GetElementType();
+
+			return TypeHelper.IsScalar(type)?
+				(IMapDataDestinationList)CreateScalarDestinationListMapper((IList)obj, type):
+				CreateObjectListMapper((IList)obj, CreateObjectMapper(type));
+		}
+
+		#endregion
+
+		#region ValueMapper
+
+		[CLSCompliant(false)]
+		public virtual IValueMapper DefaultValueMapper
+		{
+			get { return ValueMapping.DefaultMapper; }
+		}
+
+		internal readonly Dictionary<Type,IValueMapper>     SameTypeMappers      = new Dictionary<Type,IValueMapper>();
+		internal readonly Dictionary<KeyValue,IValueMapper> DifferentTypeMappers = new Dictionary<KeyValue,IValueMapper>();
+
+		[CLSCompliant(false)]
+		public void SetValueMapper(
+			Type         sourceType,
+			Type         destType,
+			IValueMapper mapper)
+		{
+			if (sourceType == null) sourceType = typeof(object);
+			if (destType   == null) destType   = typeof(object);
+
+			if (sourceType == destType)
+			{
+				lock (SameTypeMappers)
+				{
+					if (mapper == null)
+						SameTypeMappers.Remove(sourceType);
+					else if (SameTypeMappers.ContainsKey(sourceType))
+						SameTypeMappers[sourceType] = mapper;
+					else
+						SameTypeMappers.Add(sourceType, mapper);
+				}
+			}
+			else
+			{
+				KeyValue key = new KeyValue(sourceType, destType);
+
+				lock (DifferentTypeMappers)
+				{
+					if (mapper == null)
+						DifferentTypeMappers.Remove(key);
+					else if (DifferentTypeMappers.ContainsKey(key))
+						DifferentTypeMappers[key] = mapper;
+					else
+						DifferentTypeMappers.Add(key, mapper);
+				}
+			}
+		}
+
+		[CLSCompliant(false)]
+		protected internal virtual IValueMapper GetValueMapper(
+			Type sourceType,
+			Type destType)
+		{
+			return ValueMapping.GetMapper(sourceType, destType);
+		}
+
+		[CLSCompliant(false)]
+		internal protected IValueMapper[] GetValueMappers(
+			IMapDataSource      source,
+			IMapDataDestination dest,
+			int[]               index)
+		{
+			IValueMapper[] mappers = new IValueMapper[index.Length];
+
+			for (int i = 0; i < index.Length; i++)
+			{
+				int n = index[i];
+
+				if (n < 0)
+					continue;
+
+				if (!source.SupportsTypedValues(i) || !dest.SupportsTypedValues(n))
+				{
+					mappers[i] = DefaultValueMapper;
+					continue;
+				}
+
+				Type sourceType = source.GetFieldType(i);
+				Type destType   = dest.  GetFieldType(n);
+
+				if (sourceType == null) sourceType = typeof(object);
+				if (destType   == null) destType   = typeof(object);
+
+				IValueMapper t;
+
+				if (sourceType == destType)
+				{
+					lock (SameTypeMappers)
+						if (!SameTypeMappers.TryGetValue(sourceType, out t))
+							SameTypeMappers.Add(sourceType, t = GetValueMapper(sourceType, destType));
+				}
+				else
+				{
+					var key = new KeyValue(sourceType, destType);
+
+					lock (DifferentTypeMappers)
+						if (!DifferentTypeMappers.TryGetValue(key, out t))
+								DifferentTypeMappers[key] = t = GetValueMapper(sourceType, destType);
+				}
+
+				mappers[i] = t;
+			}
+
+			return mappers;
+		}
+
+		#endregion
+
+		#region Base Mapping
+
+		[CLSCompliant(false)]
+		internal protected static int[] GetIndex(
+			IMapDataSource      source,
+			IMapDataDestination dest)
+		{
+			int   count = source.Count;
+			int[] index = new int[count];
+
+			for (int i = 0; i < count; i++)
+				index[i] = dest.GetOrdinal(source.GetName(i));
+
+			return index;
+		}
+
+		[CLSCompliant(false), Obsolete]
+		protected static void MapInternal(
+			IMapDataSource      source, object sourceObject,
+			IMapDataDestination dest,   object destObject,
+			int[]               index)
+		{
+			for (int i = 0; i < index.Length; i++)
+			{
+				int n = index[i];
+
+				if (n >= 0)
+					dest.SetValue(destObject, n, source.GetValue(sourceObject, i));
+			}
+		}
+
+		[CLSCompliant(false)]
+		internal protected static void MapInternal(
+			IMapDataSource      source, object sourceObject,
+			IMapDataDestination dest,   object destObject,
+			int[]               index,
+			IValueMapper[]      mappers)
+		{
+			for (int i = 0; i < index.Length; i++)
+			{
+				int n = index[i];
+
+				if (n >= 0)
+					mappers[i].Map(source, sourceObject, i, dest, destObject, n);
+			}
+		}
+
+		[CLSCompliant(false)]
+		protected virtual void MapInternal(
+			InitContext         initContext,
+			IMapDataSource      source, object sourceObject, 
+			IMapDataDestination dest,   object destObject,
+			params object[]     parameters)
+		{
+			ISupportMapping smSource = sourceObject as ISupportMapping;
+			ISupportMapping smDest   = destObject   as ISupportMapping;
+
+			if (smSource != null)
+			{
+				if (initContext == null)
+				{
+					initContext = new InitContext();
+
+					initContext.MappingSchema = this;
+					initContext.DataSource    = source;
+					initContext.SourceObject  = sourceObject;
+					initContext.ObjectMapper  = dest as ObjectMapper;
+					initContext.Parameters    = parameters;
+				}
+
+				initContext.IsSource = true;
+				smSource.BeginMapping(initContext);
+				initContext.IsSource = false;
+
+				if (initContext.StopMapping)
+					return;
+			}
+
+			if (smDest != null)
+			{
+				if (initContext == null)
+				{
+					initContext = new InitContext();
+
+					initContext.MappingSchema = this;
+					initContext.DataSource    = source;
+					initContext.SourceObject  = sourceObject;
+					initContext.ObjectMapper  = dest as ObjectMapper;
+					initContext.Parameters    = parameters;
+				}
+
+				smDest.BeginMapping(initContext);
+
+				if (initContext.StopMapping)
+					return;
+
+				if (dest != initContext.ObjectMapper && initContext.ObjectMapper != null)
+					dest = initContext.ObjectMapper;
+			}
+
+			int[]          index   = GetIndex       (source, dest);
+			IValueMapper[] mappers = GetValueMappers(source, dest, index);
+
+			MapInternal(source, sourceObject, dest, destObject, index, mappers);
+
+			if (smDest != null)
+				smDest.EndMapping(initContext);
+
+			if (smSource != null)
+			{
+				initContext.IsSource = true;
+				smSource.EndMapping(initContext);
+				initContext.IsSource = false;
+			}
+		}
+
+		protected virtual object MapInternal(InitContext initContext)
+		{
+			object dest = initContext.ObjectMapper.CreateInstance(initContext);
+
+			if (initContext.StopMapping == false)
+			{
+				MapInternal(initContext,
+					initContext.DataSource, initContext.SourceObject,
+					initContext.ObjectMapper, dest,
+					initContext.Parameters);
+			}
+
+			return dest;
+		}
+
+		[CLSCompliant(false)]
+		public void MapSourceToDestination(
+			IMapDataSource      source, object sourceObject, 
+			IMapDataDestination dest,   object destObject,
+			params object[]     parameters)
+		{
+			MapInternal(null, source, sourceObject, dest, destObject, parameters);
+		}
+
+		public void MapSourceToDestination(
+			object          sourceObject,
+			object          destObject,
+			params object[] parameters)
+		{
+			IMapDataSource      source = GetDataSource     (sourceObject);
+			IMapDataDestination dest   = GetDataDestination(destObject);
+
+			MapInternal(null, source, sourceObject, dest, destObject, parameters);
+		}
+
+		private static readonly ObjectMapper _nullMapper = new ObjectMapper();
+
+		private class MapInfo
+		{
+			public int[]          Index;
+			public IValueMapper[] Mappers;
+		}
+
+		[CLSCompliant(false)]
+		public virtual void MapSourceListToDestinationList(
+			IMapDataSourceList      dataSourceList,
+			IMapDataDestinationList dataDestinationList,
+			params object[]         parameters)
+		{
+			if (dataSourceList      == null) throw new ArgumentNullException("dataSourceList");
+			if (dataDestinationList == null) throw new ArgumentNullException("dataDestinationList");
+
+			Dictionary<ObjectMapper,MapInfo> infos = new Dictionary<ObjectMapper,MapInfo>();
+
+			InitContext ctx = new InitContext();
+
+			ctx.MappingSchema = this;
+			ctx.Parameters    = parameters;
+
+			dataSourceList.     InitMapping(ctx); if (ctx.StopMapping) return;
+			dataDestinationList.InitMapping(ctx); if (ctx.StopMapping) return;
+
+			int[]               index   = null;
+			IValueMapper[]      mappers = null;
+			ObjectMapper        current = _nullMapper;
+			IMapDataDestination dest    = dataDestinationList.GetDataDestination(ctx);
+			ObjectMapper        om      = dest as ObjectMapper;
+
+			while (dataSourceList.SetNextDataSource(ctx))
+			{
+				ctx.ObjectMapper = om;
+				ctx.StopMapping  = false;
+
+				object destObject = dataDestinationList.GetNextObject(ctx);
+
+				if (ctx.StopMapping) continue;
+
+				ISupportMapping smSource = ctx.SourceObject as ISupportMapping;
+				ISupportMapping smDest   = destObject       as ISupportMapping;
+
+				if (smSource != null)
+				{
+					ctx.IsSource = true;
+					smSource.BeginMapping(ctx);
+					ctx.IsSource = false;
+
+					if (ctx.StopMapping)
+						continue;
+				}
+
+				if (smDest != null)
+				{
+					smDest.BeginMapping(ctx);
+
+					if (ctx.StopMapping)
+						continue;
+				}
+
+				IMapDataDestination currentDest = current ?? dest;
+
+				if (current != ctx.ObjectMapper)
+				{
+					current     = ctx.ObjectMapper;
+					currentDest = current ?? dest;
+
+					if (current != null)
+					{
+						MapInfo info;
+						if (!infos.TryGetValue(current, out info))
+						{
+							info = new MapInfo();
+
+							info.Index   = GetIndex(ctx.DataSource, currentDest);
+							info.Mappers = GetValueMappers(ctx.DataSource, currentDest, info.Index);
+
+							infos.Add(current, info);
+						}
+
+						index   = info.Index;
+						mappers = info.Mappers;
+					}
+					else
+					{
+						index   = GetIndex(ctx.DataSource, currentDest);
+						mappers = GetValueMappers(ctx.DataSource, currentDest, index);
+					}
+				}
+
+				MapInternal(
+					ctx.DataSource,
+					ctx.SourceObject,
+					currentDest,
+					destObject,
+					index,
+					mappers);
+
+				if (smDest != null)
+					smDest.EndMapping(ctx);
+
+				if (smSource != null)
+				{
+					ctx.IsSource = true;
+					smSource.EndMapping(ctx);
+					ctx.IsSource = false;
+				}
+			}
+
+			dataDestinationList.EndMapping(ctx);
+			dataSourceList.     EndMapping(ctx);
+		}
+
+		#endregion
+
+		#region ValueToEnum, EnumToValue
+
+		[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
+		public virtual object MapValueToEnum(object value, Type type)
+		{
+			if (value == null || value == DBNull.Value)
+				return GetNullValue(type);
+
+			MapValue[] mapValues = GetMapValues(type);
+
+			var mapValueType = GetMapValueType(mapValues);
+			if (mapValueType != null && value.GetType() != mapValueType)
+			{
+				value = ConvertChangeType(value, mapValueType);
+			}
+
+			if (mapValues != null)
+			{
+				var comp = (IComparable)value;
+
+				foreach (MapValue mv in mapValues)
+				foreach (object mapValue in mv.MapValues)
+				{
+					try
+					{
+						if (comp.CompareTo(mapValue) == 0)
+							return mv.OrigValue;
+					}
+					catch (ArgumentException ex)
+					{
+						Debug.WriteLine(ex.Message, MethodBase.GetCurrentMethod().Name);
+					}
+				}
+			}
+
+			InvalidCastException exInvalidCast = null;
+
+			var enumType = TypeHelper.UnwrapNullableType(type);
+			try
+			{
+				value = ConvertChangeType(value, Enum.GetUnderlyingType(enumType));
+
+				if (Enum.IsDefined(enumType, value))
+				{
+					// Regular (known) enum field w/o explicit mapping defined.
+					//
+					return Enum.ToObject(enumType, value);
+				}
+			}
+			catch (InvalidCastException ex)
+			{
+				exInvalidCast = ex;
+			}
+
+			// Default value.
+			//
+			object defaultValue = GetDefaultValue(type);
+
+			if (defaultValue != null)
+				return defaultValue;
+
+			if (exInvalidCast != null)
+			{
+				// Rethrow an InvalidCastException when no default value specified.
+				//
+				throw exInvalidCast;
+			}
+
+			// At this point we have an undefined enum value.
+			//
+			return Enum.ToObject(enumType, value);
+		}
+
+		[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
+		public virtual object MapValueToEnum(object value, MemberAccessor ma)
+		{
+			if (value == null || value is DBNull)
+				return GetNullValue(ma.Type);
+
+			MapValue[] mapValues = GetMapValues(ma);
+
+			var mapValueType = GetMapValueType(mapValues);
+			if (mapValueType != null && value.GetType() != mapValueType)
+			{
+				value = ConvertChangeType(value, mapValueType);
+			}
+
+			if (mapValues != null)
+			{
+				var comp = (IComparable)value;
+
+				foreach (MapValue mv in mapValues)
+					foreach (object mapValue in mv.MapValues)
+					{
+						try
+						{
+							if (comp.CompareTo(mapValue) == 0)
+								return mv.OrigValue;
+						}
+						catch (ArgumentException ex)
+						{
+							Debug.WriteLine(ex.Message, MethodBase.GetCurrentMethod().Name);
+						}
+					}
+			}
+
+			InvalidCastException exInvalidCast = null;
+
+			var enumType = TypeHelper.UnwrapNullableType(ma.Type);
+			try
+			{
+				value = ConvertChangeType(value, Enum.GetUnderlyingType(enumType));
+
+				if (Enum.IsDefined(enumType, value))
+				{
+					// Regular (known) enum field w/o explicit mapping defined.
+					//
+					return Enum.ToObject(enumType, value);
+				}
+			}
+			catch (InvalidCastException ex)
+			{
+				exInvalidCast = ex;
+			}
+
+			// Default value.
+			//
+			object defaultValue = GetDefaultValue(ma.Type);
+
+			if (defaultValue != null)
+				return defaultValue;
+
+			if (exInvalidCast != null)
+			{
+				// Rethrow an InvalidCastException when no default value specified.
+				//
+				throw exInvalidCast;
+			}
+
+			// At this point we have an undefined enum value.
+			//
+			return Enum.ToObject(enumType, value);
+		}
+
+		[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
+		public virtual object MapEnumToValue(object value, [JetBrains.Annotations.NotNull] Type type, bool convertToUnderlyingType)
+		{
+			if (value == null)
+				return null;
+
+			if (type == null) throw new ArgumentNullException("type");
+
+			type = value.GetType();
+
+			object nullValue = GetNullValue(type);
+
+			if (nullValue != null)
+			{
+				IComparable comp = (IComparable)value;
+
+				try
+				{
+					if (comp.CompareTo(nullValue) == 0)
+						return null;
+				}
+				catch
+				{
+				}
+			}
+
+			MapValue[] mapValues = GetMapValues(type);
+
+			if (mapValues != null)
+			{
+				IComparable comp = (IComparable)value;
+
+				foreach (MapValue mv in mapValues)
+				{
+					try
+					{
+						if (comp.CompareTo(mv.OrigValue) == 0)
+							return mv.MapValues[0];
+					}
+					catch
+					{
+					}
+				}
+			}
+
+			return convertToUnderlyingType ?
+				System.Convert.ChangeType(value, Enum.GetUnderlyingType(type), Thread.CurrentThread.CurrentCulture) :
+				value;
+		}
+
+		[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
+		public virtual object MapEnumToValue(object value, [JetBrains.Annotations.NotNull] MemberAccessor memberAccessor, bool convertToUnderlyingType)
+		{
+			if (value == null)
+				return null;
+
+			if (memberAccessor == null) throw new ArgumentNullException("memberAccessor");
+
+			if (value is IEnumerable)
+			{
+#if SILVERLIGHT
+				var result = new List<object>();
+
+				foreach (var item in (IEnumerable)value)
+				{
+					result.Add(MapEnumToValue(item, memberAccessor, convertToUnderlyingType));
+				}
+
+				var type = typeof(object);
+
+				foreach (var var in result)
+				{
+					if (var != null)
+					{
+						type = var.GetType();
+						break;
+					}
+				}
+
+				var arr = Array.CreateInstance(type, result.Count);
+
+				Array.Copy(result.ToArray(), arr, arr.Length);
+
+				return arr;
+#else
+				var result = new ArrayList();
+
+				foreach (var item in (IEnumerable)value)
+				{
+					result.Add(MapEnumToValue(item, memberAccessor, convertToUnderlyingType));
+				}
+
+				var type = typeof(object);
+
+				foreach (var var in result)
+				{
+					if (var != null)
+					{
+						type = var.GetType();
+						break;
+					}
+				}
+
+				return result.ToArray(type);
+#endif
+			}
+
+			object nullValue = GetNullValue(memberAccessor.Type);
+
+			if (nullValue != null)
+			{
+				IComparable comp = (IComparable)value;
+
+				try
+				{
+					if (comp.CompareTo(nullValue) == 0)
+						return null;
+				}
+				catch
+				{
+				}
+			}
+
+			MapValue[] mapValues = GetMapValues(memberAccessor);
+
+			if (mapValues != null)
+			{
+				IComparable comp = (IComparable)value;
+
+				foreach (MapValue mv in mapValues)
+				{
+					try
+					{
+						if (comp.CompareTo(mv.OrigValue) == 0)
+							return mv.MapValues[0];
+					}
+					catch
+					{
+					}
+				}
+			}
+
+			var memberAccessorType = TypeHelper.UnwrapNullableType(memberAccessor.Type);
+
+			return convertToUnderlyingType ?
+				System.Convert.ChangeType(value, Enum.GetUnderlyingType(memberAccessorType), Thread.CurrentThread.CurrentCulture) :
+				value;
+		}
+
+		[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
+		public virtual object MapEnumToValue(object value, bool convertToUnderlyingType)
+		{
+			if (value == null)
+				return null;
+
+			return MapEnumToValue(value, value.GetType(), convertToUnderlyingType);
+		}
+
+		public object MapEnumToValue(object value)
+		{
+			return MapEnumToValue(value, false);
+		}
+
+		public virtual object MapEnumToValue(object value, Type type)
+		{
+			return MapEnumToValue(value, type, false);
+		}
+
+		public T MapValueToEnum<T>(object value)
+		{
+			return (T)MapValueToEnum(value, typeof(T));
+		}
+
+		#endregion
+
+		#region Object
+
+		#region MapObjectToObject
+
+		public object MapObjectToObject(
+			object          sourceObject,
+			object          destObject,
+			params object[] parameters)
+		{
+			if (sourceObject == null) throw new ArgumentNullException("sourceObject");
+			if (destObject   == null) throw new ArgumentNullException("destObject");
+
+			MapInternal(
+				null,
+				GetObjectMapper(sourceObject.GetType()), sourceObject,
+				GetObjectMapper(destObject.  GetType()), destObject,
+				parameters);
+
+			return destObject;
+		}
+
+		public object MapObjectToObject(
+			object          sourceObject,
+			Type            destObjectType,
+			params object[] parameters)
+		{
+			if (sourceObject == null) throw new ArgumentNullException("sourceObject");
+
+			InitContext ctx = new InitContext();
+
+			ctx.MappingSchema = this;
+			ctx.DataSource    = GetObjectMapper(sourceObject.GetType());
+			ctx.SourceObject  = sourceObject;
+			ctx.ObjectMapper  = GetObjectMapper(destObjectType);
+			ctx.Parameters    = parameters;
+
+			return MapInternal(ctx);
+		}
+
+		public T MapObjectToObject<T>(
+			object          sourceObject,
+			params object[] parameters)
+		{
+			return (T)MapObjectToObject(sourceObject, typeof(T), parameters);
+		}
+
+		#endregion
+
+		#region MapObjectToDataRow
+
+#if !SILVERLIGHT
+
+		public DataRow MapObjectToDataRow(
+			object  sourceObject,
+			DataRow destRow)
+		{
+			if (sourceObject == null) throw new ArgumentNullException("sourceObject");
+
+			MapInternal(
+				null,
+				GetObjectMapper    (sourceObject.GetType()), sourceObject,
+				CreateDataRowMapper(destRow, DataRowVersion.Default), destRow,
+				null);
+
+			return destRow;
+		}
+
+		public DataRow MapObjectToDataRow(
+			object    sourceObject,
+			DataTable destTable)
+		{
+			if (destTable    == null) throw new ArgumentNullException("destTable");
+			if (sourceObject == null) throw new ArgumentNullException("sourceObject");
+
+			DataRow destRow = destTable.NewRow();
+
+			destTable.Rows.Add(destRow);
+
+			MapInternal(
+				null,
+				GetObjectMapper    (sourceObject.GetType()), sourceObject,
+				CreateDataRowMapper(destRow, DataRowVersion.Default), destRow,
+				null);
+
+			return destRow;
+		}
+
+#endif
+
+		#endregion
+
+		#region MapObjectToDictionary
+
+		public IDictionary MapObjectToDictionary(
+			object      sourceObject,
+			IDictionary destDictionary)
+		{
+			if (sourceObject == null) throw new ArgumentNullException("sourceObject");
+
+			MapInternal(
+				null,
+				GetObjectMapper       (sourceObject.GetType()), sourceObject,
+				CreateDictionaryMapper(destDictionary),         destDictionary,
+				null);
+
+			return destDictionary;
+		}
+
+		public IDictionary MapObjectToDictionary(object sourceObject)
+		{
+			if (sourceObject == null) throw new ArgumentNullException("sourceObject");
+
+			ObjectMapper om = GetObjectMapper(sourceObject.GetType());
+
+			var destDictionary = new Dictionary<object,object>(om.Count);
+
+			MapInternal(
+				null,
+				om, sourceObject,
+				CreateDictionaryMapper(destDictionary), destDictionary,
+				null);
+
+			return destDictionary;
+		}
+
+		#endregion
+
+		#endregion
+
+		#region DataRow
+
+#if !SILVERLIGHT
+
+		#region MapDataRowToObject
+
+		public object MapDataRowToObject(
+			DataRow         dataRow,
+			object          destObject,
+			params object[] parameters)
+		{
+			if (destObject == null) throw new ArgumentNullException("destObject");
+
+			MapInternal(
+				null,
+				CreateDataRowMapper(dataRow, DataRowVersion.Default), dataRow,
+				GetObjectMapper(destObject.  GetType()), destObject,
+				parameters);
+
+			return destObject;
+		}
+
+		public object MapDataRowToObject(
+			DataRow         dataRow,
+			DataRowVersion  version,
+			object          destObject,
+			params object[] parameters)
+		{
+			if (destObject == null) throw new ArgumentNullException("destObject");
+
+			MapInternal(
+				null,
+				CreateDataRowMapper(dataRow, version), dataRow,
+				GetObjectMapper(destObject.  GetType()), destObject,
+				parameters);
+
+			return destObject;
+		}
+
+		public object MapDataRowToObject(
+			DataRow         dataRow,
+			Type            destObjectType,
+			params object[] parameters)
+		{
+			InitContext ctx = new InitContext();
+
+			ctx.MappingSchema = this;
+			ctx.DataSource    = CreateDataRowMapper(dataRow, DataRowVersion.Default);
+			ctx.SourceObject  = dataRow;
+			ctx.ObjectMapper  = GetObjectMapper(destObjectType);
+			ctx.Parameters    = parameters;
+
+			return MapInternal(ctx);
+		}
+
+		public object MapDataRowToObject(
+			DataRow         dataRow,
+			DataRowVersion  version,
+			Type            destObjectType,
+			params object[] parameters)
+		{
+			InitContext ctx = new InitContext();
+
+			ctx.MappingSchema = this;
+			ctx.DataSource    = CreateDataRowMapper(dataRow, version);
+			ctx.SourceObject  = dataRow;
+			ctx.ObjectMapper  = GetObjectMapper(destObjectType);
+			ctx.Parameters    = parameters;
+
+			return MapInternal(ctx);
+		}
+
+		public T MapDataRowToObject<T>(
+			DataRow         dataRow,
+			params object[] parameters)
+		{
+			return (T)MapDataRowToObject(dataRow, typeof(T), parameters);
+		}
+
+		public T MapDataRowToObject<T>(
+			DataRow         dataRow,
+			DataRowVersion  version,
+			params object[] parameters)
+		{
+			return (T)MapDataRowToObject(dataRow, version, typeof(T), parameters);
+		}
+
+		#endregion
+
+		#region MapDataRowToDataRow
+
+		public DataRow MapDataRowToDataRow(
+			DataRow sourceRow,
+			DataRow destRow)
+		{
+			MapInternal(
+				null,
+				CreateDataRowMapper(sourceRow, DataRowVersion.Default), sourceRow,
+				CreateDataRowMapper(destRow,   DataRowVersion.Default), destRow,
+				null);
+
+			return destRow;
+		}
+
+		public DataRow MapDataRowToDataRow(
+			DataRow        sourceRow,
+			DataRowVersion version,
+			DataRow        destRow)
+		{
+			MapInternal(
+				null,
+				CreateDataRowMapper(sourceRow, version), sourceRow,
+				CreateDataRowMapper(destRow, DataRowVersion.Default), destRow,
+				null);
+
+			return destRow;
+		}
+
+		public DataRow MapDataRowToDataRow(
+			DataRow   sourceRow,
+			DataTable destTable)
+		{
+			if (destTable == null) throw new ArgumentNullException("destTable");
+
+			DataRow destRow = destTable.NewRow();
+
+			destTable.Rows.Add(destRow);
+
+			MapInternal(
+				null,
+				CreateDataRowMapper(sourceRow, DataRowVersion.Default), sourceRow,
+				CreateDataRowMapper(destRow,   DataRowVersion.Default), destRow,
+				null);
+
+			return destRow;
+		}
+
+		public DataRow MapDataRowToDataRow(
+			DataRow        sourceRow,
+			DataRowVersion version,
+			DataTable      destTable)
+		{
+			if (destTable == null) throw new ArgumentNullException("destTable");
+
+			DataRow destRow = destTable.NewRow();
+
+			destTable.Rows.Add(destRow);
+
+			MapInternal(
+				null,
+				CreateDataRowMapper(sourceRow, version), sourceRow,
+				CreateDataRowMapper(destRow, DataRowVersion.Default), destRow,
+				null);
+
+			return destRow;
+		}
+
+		#endregion
+
+		#region MapDataRowToDictionary
+
+		public IDictionary MapDataRowToDictionary(
+			DataRow sourceRow,
+			IDictionary destDictionary)
+		{
+			MapInternal(
+				null,
+				CreateDataRowMapper   (sourceRow, DataRowVersion.Default), sourceRow,
+				CreateDictionaryMapper(destDictionary),                    destDictionary,
+				null);
+
+			return destDictionary;
+		}
+
+		public Hashtable MapDataRowToDictionary(DataRow sourceRow)
+		{
+			if (sourceRow == null) throw new ArgumentNullException("sourceRow");
+
+			Hashtable destDictionary = new Hashtable(sourceRow.Table.Columns.Count);
+
+			MapInternal(
+				null,
+				CreateDataRowMapper   (sourceRow, DataRowVersion.Default), sourceRow,
+				CreateDictionaryMapper(destDictionary),                    destDictionary,
+				null);
+
+			return destDictionary;
+		}
+
+		public IDictionary MapDataRowToDictionary(
+			DataRow        sourceRow,
+			DataRowVersion version,
+			IDictionary    destDictionary)
+		{
+			MapInternal(
+				null,
+				CreateDataRowMapper   (sourceRow, version), sourceRow,
+				CreateDictionaryMapper(destDictionary),     destDictionary,
+				null);
+
+			return destDictionary;
+		}
+
+		public Hashtable MapDataRowToDictionary(
+			DataRow        sourceRow,
+			DataRowVersion version)
+		{
+			if (sourceRow == null) throw new ArgumentNullException("sourceRow");
+
+			Hashtable destDictionary = new Hashtable(sourceRow.Table.Columns.Count);
+
+			MapInternal(
+				null,
+				CreateDataRowMapper   (sourceRow, version), sourceRow,
+				CreateDictionaryMapper(destDictionary),     destDictionary,
+				null);
+
+			return destDictionary;
+		}
+
+		#endregion
+
+#endif
+
+		#endregion
+
+		#region DataReader
+
+		#region MapDataReaderToObject
+
+		public object MapDataReaderToObject(
+			IDataReader     dataReader,
+			object          destObject,
+			params object[] parameters)
+		{
+			if (destObject == null) throw new ArgumentNullException("destObject");
+
+			MapInternal(
+				null,
+				CreateDataReaderMapper(dataReader), dataReader,
+				GetObjectMapper(destObject. GetType()), destObject,
+				parameters);
+
+			return destObject;
+		}
+
+		//NOTE changed to virtual
+		public virtual object MapDataReaderToObject(
+			IDataReader     dataReader,
+			Type            destObjectType,
+			params object[] parameters)
+		{
+			InitContext ctx = new InitContext();
+
+			ctx.MappingSchema = this;
+			ctx.DataSource    = CreateDataReaderMapper(dataReader);
+			ctx.SourceObject  = dataReader;
+			ctx.ObjectMapper  = GetObjectMapper(destObjectType);
+			ctx.Parameters    = parameters;
+
+			return MapInternal(ctx);
+		}
+
+		public T MapDataReaderToObject<T>(
+			IDataReader     dataReader,
+			params object[] parameters)
+		{
+			return (T)MapDataReaderToObject(dataReader, typeof(T), parameters);
+		}
+
+		#endregion
+
+		#region MapDataReaderToDataRow
+
+#if !SILVERLIGHT
+
+		public DataRow MapDataReaderToDataRow(IDataReader dataReader, DataRow destRow)
+		{
+			MapInternal(
+				null,
+				CreateDataReaderMapper(dataReader), dataReader,
+				CreateDataRowMapper(destRow, DataRowVersion.Default), destRow,
+				null);
+
+			return destRow;
+		}
+
+		public DataRow MapDataReaderToDataRow(
+			IDataReader dataReader,
+			DataTable   destTable)
+		{
+			if (destTable == null) throw new ArgumentNullException("destTable");
+
+			DataRow destRow = destTable.NewRow();
+
+			destTable.Rows.Add(destRow);
+
+			MapInternal(
+				null,
+				CreateDataReaderMapper(dataReader), dataReader,
+				CreateDataRowMapper(destRow, DataRowVersion.Default), destRow,
+				null);
+
+			return destRow;
+		}
+
+#endif
+
+		#endregion
+
+		#region MapDataReaderToDictionary
+
+		public IDictionary MapDataReaderToDictionary(
+			IDataReader dataReader,
+			IDictionary destDictionary)
+		{
+			MapInternal(
+				null,
+				CreateDataReaderMapper(dataReader),     dataReader,
+				CreateDictionaryMapper(destDictionary), destDictionary,
+				null);
+
+			return destDictionary;
+		}
+
+		public IDictionary MapDataReaderToDictionary(IDataReader dataReader)
+		{
+			if (dataReader == null) throw new ArgumentNullException("dataReader");
+
+			var destDictionary = new Dictionary<object,object>(dataReader.FieldCount);
+
+			MapInternal(
+				null,
+				CreateDataReaderMapper(dataReader),     dataReader,
+				CreateDictionaryMapper(destDictionary), destDictionary,
+				null);
+
+			return destDictionary;
+		}
+
+		#endregion
+
+		#endregion
+
+		#region Dictionary
+
+		#region MapDictionaryToObject
+
+		public object MapDictionaryToObject(
+			IDictionary     sourceDictionary,
+			object          destObject,
+			params object[] parameters)
+		{
+			if (destObject == null) throw new ArgumentNullException("destObject");
+
+			MapInternal(
+				null,
+				CreateDictionaryMapper(sourceDictionary),       sourceDictionary,
+				GetObjectMapper       (destObject.  GetType()), destObject,
+				parameters);
+
+			return destObject;
+		}
+
+		public object MapDictionaryToObject(
+			IDictionary     sourceDictionary,
+			Type            destObjectType,
+			params object[] parameters)
+		{
+			InitContext ctx = new InitContext();
+
+			ctx.MappingSchema = this;
+			ctx.DataSource    = CreateDictionaryMapper(sourceDictionary);
+			ctx.SourceObject  = sourceDictionary;
+			ctx.ObjectMapper  = GetObjectMapper(destObjectType);
+			ctx.Parameters    = parameters;
+
+			return MapInternal(ctx);
+		}
+
+		public T MapDictionaryToObject<T>(IDictionary sourceDictionary, params object[] parameters)
+		{
+			return (T)MapDictionaryToObject(sourceDictionary, typeof(T), parameters);
+		}
+
+		#endregion
+
+		#region MapDictionaryToDataRow
+
+#if !SILVERLIGHT
+
+		public DataRow MapDictionaryToDataRow(
+			IDictionary sourceDictionary,
+			DataRow     destRow)
+		{
+			MapInternal(
+				null,
+				CreateDictionaryMapper(sourceDictionary),                sourceDictionary,
+				CreateDataRowMapper   (destRow, DataRowVersion.Default), destRow,
+				null);
+
+			return destRow;
+		}
+
+		public DataRow MapDictionaryToDataRow(
+			IDictionary sourceDictionary,
+			DataTable   destTable)
+		{
+			if (destTable == null) throw new ArgumentNullException("destTable");
+
+			DataRow destRow = destTable.NewRow();
+
+			destTable.Rows.Add(destRow);
+
+			MapInternal(
+				null,
+				CreateDictionaryMapper(sourceDictionary),                sourceDictionary,
+				CreateDataRowMapper   (destRow, DataRowVersion.Default), destRow,
+				null);
+
+			return destRow;
+		}
+
+#endif
+
+		#endregion
+
+		#endregion
+
+		#region List
+
+		#region MapListToList
+
+		public IList MapListToList(
+			ICollection     sourceList,
+			IList           destList,
+			Type            destObjectType,
+			params object[] parameters)
+		{
+			if (sourceList == null) throw new ArgumentNullException("sourceList");
+
+			MapSourceListToDestinationList(
+				CreateEnumeratorMapper(sourceList.GetEnumerator()),
+				CreateObjectListMapper(destList, GetObjectMapper(destObjectType)),
+				parameters);
+
+			return destList;
+		}
+
+		public IList MapListToList(
+			ICollection     sourceList,
+			Type            destObjectType,
+			params object[] parameters)
+		{
+			if (sourceList == null) throw new ArgumentNullException("sourceList");
+
+			var destList = new List<object>();
+
+			MapSourceListToDestinationList(
+				CreateEnumeratorMapper(sourceList.GetEnumerator()),
+				CreateObjectListMapper(destList, GetObjectMapper(destObjectType)),
+				parameters);
+
+			return destList;
+		}
+
+		public List<T> MapListToList<T>(
+			ICollection     sourceList,
+			List<T>         destList,
+			params object[] parameters)
+		{
+			MapSourceListToDestinationList(
+				CreateEnumeratorMapper(sourceList.GetEnumerator()),
+				CreateObjectListMapper(destList, GetObjectMapper(typeof(T))),
+				parameters);
+
+			return destList;
+		}
+
+		public List<T> MapListToList<T>(
+			ICollection     sourceList,
+			params object[] parameters)
+		{
+			List<T> destList = new List<T>();
+
+			MapSourceListToDestinationList(
+				CreateEnumeratorMapper(sourceList.GetEnumerator()),
+				CreateObjectListMapper(destList, GetObjectMapper(typeof(T))),
+				parameters);
+
+			return destList;
+		}
+
+		#endregion
+
+		#region MapListToDataTable
+
+#if !SILVERLIGHT
+
+		public DataTable MapListToDataTable(
+			ICollection sourceList,
+			DataTable   destTable)
+		{
+			if (sourceList == null) throw new ArgumentNullException("sourceList");
+
+			MapSourceListToDestinationList(
+				CreateEnumeratorMapper(sourceList.GetEnumerator()),
+				CreateDataTableMapper (destTable, DataRowVersion.Default),
+				null);
+
+			return destTable;
+		}
+
+		[SuppressMessage("Microsoft.Globalization", "CA1306:SetLocaleForDataTypes")]
+		public DataTable MapListToDataTable(ICollection sourceList)
+		{
+			if (sourceList == null) throw new ArgumentNullException("sourceList");
+
+			DataTable destTable = new DataTable();
+
+			MapSourceListToDestinationList(
+				CreateEnumeratorMapper(sourceList.GetEnumerator()),
+				CreateDataTableMapper (destTable, DataRowVersion.Default),
+				null);
+
+			return destTable;
+		}
+
+#endif
+
+		#endregion
+
+		#region MapListToDictionary
+
+		public IDictionary MapListToDictionary(
+			ICollection          sourceList,
+			IDictionary          destDictionary,
+			NameOrIndexParameter keyFieldNameOrIndex,
+			Type                 destObjectType,
+			params object[]      parameters)
+		{
+			if (sourceList == null) throw new ArgumentNullException("sourceList");
+
+			MapSourceListToDestinationList(
+				CreateEnumeratorMapper    (sourceList.GetEnumerator()),
+				CreateDictionaryListMapper(destDictionary, keyFieldNameOrIndex, GetObjectMapper(destObjectType)),
+				parameters);
+
+			return destDictionary;
+		}
+
+		public IDictionary MapListToDictionary(
+			ICollection          sourceList,
+			NameOrIndexParameter keyFieldNameOrIndex,
+			Type                 destObjectType,
+			params object[]      parameters)
+		{
+			if (sourceList == null) throw new ArgumentNullException("sourceList");
+
+			IDictionary destDictionary = new Dictionary<object,object>();
+
+			MapSourceListToDestinationList(
+				CreateEnumeratorMapper    (sourceList.GetEnumerator()),
+				CreateDictionaryListMapper(destDictionary, keyFieldNameOrIndex, GetObjectMapper(destObjectType)),
+				parameters);
+
+			return destDictionary;
+		}
+
+		public IDictionary<TK,T> MapListToDictionary<TK,T>(
+			ICollection          sourceList,
+			IDictionary<TK,T>     destDictionary,
+			NameOrIndexParameter keyFieldNameOrIndex,
+			params object[]      parameters)
+		{
+			MapSourceListToDestinationList(
+				CreateEnumeratorMapper         (sourceList.GetEnumerator()),
+				CreateDictionaryListMapper<TK,T>(destDictionary, keyFieldNameOrIndex, GetObjectMapper(typeof(T))),
+				parameters);
+
+			return destDictionary;
+		}
+
+		public Dictionary<TK,T> MapListToDictionary<TK,T>(
+			ICollection          sourceList,
+			NameOrIndexParameter keyFieldNameOrIndex,
+			params object[]      parameters)
+		{
+			Dictionary<TK,T> destDictionary = new Dictionary<TK,T>();
+
+			MapSourceListToDestinationList(
+				CreateEnumeratorMapper          (sourceList.GetEnumerator()),
+				CreateDictionaryListMapper<TK,T>(destDictionary, keyFieldNameOrIndex, GetObjectMapper(typeof(T))),
+				parameters);
+
+			return destDictionary;
+		}
+
+		#endregion
+
+		#region MapListToDictionaryIndex
+
+		public IDictionary MapListToDictionary(
+			ICollection     sourceList,
+			IDictionary     destDictionary,
+			MapIndex        index,
+			Type            destObjectType,
+			params object[] parameters)
+		{
+			if (sourceList == null) throw new ArgumentNullException("sourceList");
+
+			MapSourceListToDestinationList(
+				CreateEnumeratorMapper    (sourceList.GetEnumerator()),
+				CreateDictionaryListMapper(destDictionary, index, GetObjectMapper(destObjectType)),
+				parameters);
+
+			return destDictionary;
+		}
+
+		public IDictionary MapListToDictionary(
+			ICollection     sourceList,
+			MapIndex        index,
+			Type            destObjectType,
+			params object[] parameters)
+		{
+			if (sourceList == null) throw new ArgumentNullException("sourceList");
+
+			IDictionary destDictionary = new Dictionary<object,object>();
+
+			MapSourceListToDestinationList(
+				CreateEnumeratorMapper    (sourceList.GetEnumerator()),
+				CreateDictionaryListMapper(destDictionary, index, GetObjectMapper(destObjectType)),
+				parameters);
+
+			return destDictionary;
+		}
+
+		public IDictionary<CompoundValue,T> MapListToDictionary<T>(
+			ICollection                  sourceList,
+			IDictionary<CompoundValue,T> destDictionary,
+			MapIndex                     index,
+			params object[]              parameters)
+		{
+			MapSourceListToDestinationList(
+				CreateEnumeratorMapper       (sourceList.GetEnumerator()),
+				CreateDictionaryListMapper<T>(destDictionary, index, GetObjectMapper(typeof(T))),
+				parameters);
+
+			return destDictionary;
+		}
+
+		public Dictionary<CompoundValue,T> MapListToDictionary<T>(
+			ICollection     sourceList,
+			MapIndex        index,
+			params object[] parameters)
+		{
+			Dictionary<CompoundValue, T> destDictionary = new Dictionary<CompoundValue,T>();
+
+			MapSourceListToDestinationList(
+				CreateEnumeratorMapper       (sourceList.GetEnumerator()),
+				CreateDictionaryListMapper<T>(destDictionary, index, GetObjectMapper(typeof(T))),
+				parameters);
+
+			return destDictionary;
+		}
+
+		#endregion
+
+		#endregion
+
+		#region Table
+
+#if !SILVERLIGHT
+
+
+		#region MapDataTableToDataTable
+
+		public DataTable MapDataTableToDataTable(
+			DataTable sourceTable,
+			DataTable destTable)
+		{
+			MapSourceListToDestinationList(
+				CreateDataTableMapper(sourceTable, DataRowVersion.Default),
+				CreateDataTableMapper(destTable,   DataRowVersion.Default),
+				null);
+
+			return destTable;
+		}
+
+		public DataTable MapDataTableToDataTable(
+			DataTable      sourceTable,
+			DataRowVersion version,
+			DataTable      destTable)
+		{
+			MapSourceListToDestinationList(
+				CreateDataTableMapper(sourceTable, version),
+				CreateDataTableMapper(destTable,   DataRowVersion.Default),
+				null);
+
+			return destTable;
+		}
+
+		public DataTable MapDataTableToDataTable(DataTable sourceTable)
+		{
+			if (sourceTable == null) throw new ArgumentNullException("sourceTable");
+
+			DataTable destTable = sourceTable.Clone();
+
+			MapSourceListToDestinationList(
+				CreateDataTableMapper(sourceTable, DataRowVersion.Default),
+				CreateDataTableMapper(destTable,   DataRowVersion.Default),
+				null);
+
+			return destTable;
+		}
+
+		public DataTable MapDataTableToDataTable(
+			DataTable      sourceTable,
+			DataRowVersion version)
+		{
+			if (sourceTable == null) throw new ArgumentNullException("sourceTable");
+
+			DataTable destTable = sourceTable.Clone();
+
+			MapSourceListToDestinationList(
+				CreateDataTableMapper(sourceTable, version),
+				CreateDataTableMapper(destTable,   DataRowVersion.Default),
+				null);
+
+			return destTable;
+		}
+
+		#endregion
+
+		#region MapDataTableToList
+
+		public IList MapDataTableToList(
+			DataTable       sourceTable,
+			IList           list,
+			Type            destObjectType,
+			params object[] parameters)
+		{
+			MapSourceListToDestinationList(
+				CreateDataTableMapper (sourceTable, DataRowVersion.Default),
+				CreateObjectListMapper(list, GetObjectMapper(destObjectType)),
+				parameters);
+
+			return list;
+		}
+
+		public IList MapDataTableToList(
+			DataTable       sourceTable,
+			DataRowVersion  version,
+			IList           list,
+			Type            destObjectType,
+			params object[] parameters)
+		{
+			MapSourceListToDestinationList(
+				CreateDataTableMapper (sourceTable, version),
+				CreateObjectListMapper(list, GetObjectMapper(destObjectType)),
+				parameters);
+
+			return list;
+		}
+
+		public ArrayList MapDataTableToList(
+			DataTable       sourceTable,
+			Type            destObjectType,
+			params object[] parameters)
+		{
+			ArrayList list = new ArrayList();
+
+			MapSourceListToDestinationList(
+				CreateDataTableMapper (sourceTable, DataRowVersion.Default),
+				CreateObjectListMapper(list, GetObjectMapper(destObjectType)),
+				parameters);
+
+			return list;
+		}
+
+		public ArrayList MapDataTableToList(
+			DataTable       sourceTable,
+			DataRowVersion  version,
+			Type            destObjectType,
+			params object[] parameters)
+		{
+			ArrayList list = new ArrayList();
+
+			MapSourceListToDestinationList(
+				CreateDataTableMapper (sourceTable, version),
+				CreateObjectListMapper(list, GetObjectMapper(destObjectType)),
+				parameters);
+
+			return list;
+		}
+
+		public List<T> MapDataTableToList<T>(
+			DataTable       sourceTable,
+			List<T>         list,
+			params object[] parameters)
+		{
+			MapSourceListToDestinationList(
+				CreateDataTableMapper (sourceTable, DataRowVersion.Default),
+				CreateObjectListMapper(list, GetObjectMapper(typeof(T))),
+				parameters);
+
+			return list;
+		}
+
+		public List<T> MapDataTableToList<T>(
+			DataTable       sourceTable,
+			DataRowVersion  version,
+			List<T>         list,
+			params object[] parameters)
+		{
+			MapSourceListToDestinationList(
+				CreateDataTableMapper (sourceTable, version),
+				CreateObjectListMapper(list, GetObjectMapper(typeof(T))),
+				parameters);
+
+			return list;
+		}
+
+		public List<T> MapDataTableToList<T>(
+			DataTable       sourceTable,
+			params object[] parameters)
+		{
+			List<T> list = new List<T>();
+
+			MapSourceListToDestinationList(
+				CreateDataTableMapper (sourceTable, DataRowVersion.Default),
+				CreateObjectListMapper(list, GetObjectMapper(typeof(T))),
+				parameters);
+
+			return list;
+		}
+
+		public List<T> MapDataTableToList<T>(
+			DataTable       sourceTable,
+			DataRowVersion  version,
+			params object[] parameters)
+		{
+			List<T> list = new List<T>();
+
+			MapSourceListToDestinationList(
+				CreateDataTableMapper (sourceTable, version),
+				CreateObjectListMapper(list, GetObjectMapper(typeof(T))),
+				parameters);
+
+			return list;
+		}
+
+		#endregion
+
+		#region MapDataTableToDictionary
+
+		public IDictionary MapDataTableToDictionary(
+			DataTable            sourceTable,
+			IDictionary          destDictionary,
+			NameOrIndexParameter keyFieldNameOrIndex,
+			Type                 destObjectType,
+			params object[]      parameters)
+		{
+			MapSourceListToDestinationList(
+				CreateDataTableMapper     (sourceTable,    DataRowVersion.Default),
+				CreateDictionaryListMapper(destDictionary, keyFieldNameOrIndex, GetObjectMapper(destObjectType)),
+				parameters);
+
+			return destDictionary;
+		}
+
+		public Hashtable MapDataTableToDictionary(
+			DataTable            sourceTable,
+			NameOrIndexParameter keyFieldNameOrIndex,
+			Type                 destObjectType,
+			params object[]      parameters)
+		{
+			Hashtable destDictionary = new Hashtable();
+
+			MapSourceListToDestinationList(
+				CreateDataTableMapper     (sourceTable,    DataRowVersion.Default),
+				CreateDictionaryListMapper(destDictionary, keyFieldNameOrIndex, GetObjectMapper(destObjectType)),
+				parameters);
+
+			return destDictionary;
+		}
+
+		public IDictionary<TK,T> MapDataTableToDictionary<TK,T>(
+			DataTable            sourceTable,
+			IDictionary<TK,T>     destDictionary,
+			NameOrIndexParameter keyFieldNameOrIndex,
+			params object[]      parameters)
+		{
+			MapSourceListToDestinationList(
+				CreateDataTableMapper          (sourceTable,    DataRowVersion.Default),
+				CreateDictionaryListMapper<TK,T>(destDictionary, keyFieldNameOrIndex, GetObjectMapper(typeof(T))),
+				parameters);
+
+			return destDictionary;
+		}
+
+		public Dictionary<TK,T> MapDataTableToDictionary<TK,T>(
+			DataTable            sourceTable,
+			NameOrIndexParameter keyFieldNameOrIndex,
+			params object[]      parameters)
+		{
+			Dictionary<TK,T> destDictionary = new Dictionary<TK,T>();
+
+			MapSourceListToDestinationList(
+				CreateDataTableMapper          (sourceTable,    DataRowVersion.Default),
+				CreateDictionaryListMapper<TK,T>(destDictionary, keyFieldNameOrIndex, GetObjectMapper(typeof(T))),
+				parameters);
+
+			return destDictionary;
+		}
+
+		#endregion
+
+		#region MapDataTableToDictionary (Index)
+
+		public IDictionary MapDataTableToDictionary(
+			DataTable       sourceTable,
+			IDictionary     destDictionary,
+			MapIndex        index,
+			Type            destObjectType,
+			params object[] parameters)
+		{
+			MapSourceListToDestinationList(
+				CreateDataTableMapper     (sourceTable,    DataRowVersion.Default),
+				CreateDictionaryListMapper(destDictionary, index, GetObjectMapper(destObjectType)),
+				parameters);
+
+			return destDictionary;
+		}
+
+		public Hashtable MapDataTableToDictionary(
+			DataTable       sourceTable,
+			MapIndex        index,
+			Type            destObjectType,
+			params object[] parameters)
+		{
+			Hashtable destDictionary = new Hashtable();
+
+			MapSourceListToDestinationList(
+				CreateDataTableMapper     (sourceTable,    DataRowVersion.Default),
+				CreateDictionaryListMapper(destDictionary, index, GetObjectMapper(destObjectType)),
+				parameters);
+
+			return destDictionary;
+		}
+
+		public IDictionary<CompoundValue,T> MapDataTableToDictionary<T>(
+			DataTable                    sourceTable,
+			IDictionary<CompoundValue,T> destDictionary,
+			MapIndex                     index,
+			params object[]              parameters)
+		{
+			MapSourceListToDestinationList(
+				CreateDataTableMapper        (sourceTable,    DataRowVersion.Default),
+				CreateDictionaryListMapper<T>(destDictionary, index, GetObjectMapper(typeof(T))),
+				parameters);
+
+			return destDictionary;
+		}
+
+		public Dictionary<CompoundValue,T> MapDataTableToDictionary<T>(
+			DataTable       sourceTable,
+			MapIndex        index,
+			params object[] parameters)
+		{
+			Dictionary<CompoundValue,T> destDictionary = new Dictionary<CompoundValue,T>();
+
+			MapSourceListToDestinationList(
+				CreateDataTableMapper        (sourceTable,    DataRowVersion.Default),
+				CreateDictionaryListMapper<T>(destDictionary, index, GetObjectMapper(typeof(T))),
+				parameters);
+
+			return destDictionary;
+		}
+
+		#endregion
+
+#endif
+
+		#endregion
+
+		#region DataReader
+
+		#region MapDataReaderToList
+
+		public virtual IList MapDataReaderToList(
+			IDataReader     reader,
+			IList           list,
+			Type            destObjectType,
+			params object[] parameters)
+		{
+			MapSourceListToDestinationList(
+				CreateDataReaderListMapper(reader),
+				CreateObjectListMapper    (list, GetObjectMapper(destObjectType)),
+				parameters);
+
+			return list;
+		}
+
+		public IList MapDataReaderToList(
+			IDataReader     reader,
+			Type            destObjectType,
+			params object[] parameters)
+		{
+			IList list = new List<object>();
+
+			MapSourceListToDestinationList(
+				CreateDataReaderListMapper(reader),
+				CreateObjectListMapper    (list, GetObjectMapper(destObjectType)),
+				parameters);
+
+			return list;
+		}
+
+		//NOTE changed to virtual
+		public virtual IList<T> MapDataReaderToList<T>(
+			IDataReader     reader,
+			IList<T>        list,
+			params object[] parameters)
+		{
+			MapSourceListToDestinationList(
+				CreateDataReaderListMapper(reader),
+				CreateObjectListMapper    ((IList)list, GetObjectMapper(typeof(T))),
+				parameters);
+
+			return list;
+		}
+
+		public List<T> MapDataReaderToList<T>(
+			IDataReader     reader,
+			params object[] parameters)
+		{
+			List<T> list = new List<T>();
+
+			MapSourceListToDestinationList(
+				CreateDataReaderListMapper(reader),
+				CreateObjectListMapper    (list, GetObjectMapper(typeof(T))),
+				parameters);
+
+			return list;
+		}
+
+		#endregion
+
+		#region MapDataReaderToScalarList
+
+		public IList MapDataReaderToScalarList(
+			IDataReader          reader,
+			NameOrIndexParameter nameOrIndex,
+			IList                list,
+			Type                 type)
+		{
+			MapSourceListToDestinationList(
+				CreateDataReaderListMapper(reader, nameOrIndex),
+				CreateScalarDestinationListMapper(list,   type),
+				null);
+
+			return list;
+		}
+
+		public IList MapDataReaderToScalarList(
+			IDataReader          reader,
+			NameOrIndexParameter nameOrIndex,
+			Type                 type)
+		{
+			IList list = new List<object>();
+
+			MapSourceListToDestinationList(
+				CreateDataReaderListMapper(reader, nameOrIndex),
+				CreateScalarDestinationListMapper(list,   type),
+				null);
+
+			return list;
+		}
+
+		public IList<T> MapDataReaderToScalarList<T>(
+			IDataReader          reader,
+			NameOrIndexParameter nameOrIndex,
+			IList<T>             list)
+		{
+			MapSourceListToDestinationList(
+				CreateDataReaderListMapper(reader, nameOrIndex),
+				CreateScalarDestinationListMapper(list),
+				null);
+
+			return list;
+		}
+
+		public List<T> MapDataReaderToScalarList<T>(
+			IDataReader          reader,
+			NameOrIndexParameter nameOrIndex)
+		{
+			List<T> list = new List<T>();
+
+			MapSourceListToDestinationList(
+				CreateDataReaderListMapper(reader, nameOrIndex),
+				CreateScalarDestinationListMapper(list),
+				null);
+
+			return list;
+		}
+
+		#endregion
+
+		#region MapDataReaderToDataTable
+
+#if !SILVERLIGHT
+
+		public DataTable MapDataReaderToDataTable(
+			IDataReader reader,
+			DataTable   destTable)
+		{
+			MapSourceListToDestinationList(
+				CreateDataReaderListMapper(reader),
+				CreateDataTableMapper     (destTable, DataRowVersion.Default),
+				null);
+
+			return destTable;
+		}
+
+		[SuppressMessage("Microsoft.Globalization", "CA1306:SetLocaleForDataTypes")]
+		public DataTable MapDataReaderToDataTable(IDataReader reader)
+		{
+			DataTable destTable = new DataTable();
+
+			MapSourceListToDestinationList(
+				CreateDataReaderListMapper(reader),
+				CreateDataTableMapper     (destTable, DataRowVersion.Default),
+				null);
+
+			return destTable;
+		}
+
+#endif
+
+		#endregion
+
+		#region MapDataReaderToDictionary
+
+		public IDictionary MapDataReaderToDictionary(
+			IDataReader          reader,
+			IDictionary          destDictionary,
+			NameOrIndexParameter keyFieldNameOrIndex,
+			Type                 destObjectType,
+			params object[]      parameters)
+		{
+			MapSourceListToDestinationList(
+				CreateDataReaderListMapper(reader),
+				CreateDictionaryListMapper(destDictionary, keyFieldNameOrIndex, GetObjectMapper(destObjectType)),
+				parameters);
+
+			return destDictionary;
+		}
+
+		public IDictionary MapDataReaderToDictionary(
+			IDataReader          reader,
+			NameOrIndexParameter keyFieldNameOrIndex,
+			Type                 destObjectType,
+			params object[]      parameters)
+		{
+			IDictionary dest = new Dictionary<object,object>();
+
+			MapSourceListToDestinationList(
+				CreateDataReaderListMapper(reader),
+				CreateDictionaryListMapper(dest, keyFieldNameOrIndex, GetObjectMapper(destObjectType)),
+				parameters);
+
+			return dest;
+		}
+
+		public IDictionary<TK,T> MapDataReaderToDictionary<TK,T>(
+			IDataReader          reader,
+			IDictionary<TK,T>     destDictionary,
+			NameOrIndexParameter keyFieldNameOrIndex,
+			Type                 destObjectType,
+			params object[]      parameters)
+		{
+			MapSourceListToDestinationList(
+				CreateDataReaderListMapper     (reader),
+				CreateDictionaryListMapper<TK,T>(destDictionary, keyFieldNameOrIndex, GetObjectMapper(destObjectType)),
+				parameters);
+
+			return destDictionary;
+		}
+
+		public IDictionary<TK,T> MapDataReaderToDictionary<TK,T>(
+			IDataReader          reader,
+			IDictionary<TK,T>     destDictionary,
+			NameOrIndexParameter keyFieldNameOrIndex,
+			params object[]      parameters)
+		{
+			MapSourceListToDestinationList(
+				CreateDataReaderListMapper     (reader),
+				CreateDictionaryListMapper<TK,T>(destDictionary, keyFieldNameOrIndex, GetObjectMapper(typeof(T))),
+				parameters);
+
+			return destDictionary;
+		}
+
+		public Dictionary<TK,T> MapDataReaderToDictionary<TK,T>(
+			IDataReader          reader,
+			NameOrIndexParameter keyFieldNameOrIndex,
+			params object[]      parameters)
+		{
+			Dictionary<TK,T> dest = new Dictionary<TK,T>();
+
+			MapSourceListToDestinationList(
+				CreateDataReaderListMapper     (reader),
+				CreateDictionaryListMapper<TK,T>(dest, keyFieldNameOrIndex, GetObjectMapper(typeof(T))),
+				parameters);
+
+			return dest;
+		}
+
+		#endregion
+
+		#region MapDataReaderToDictionary (Index)
+
+		public IDictionary MapDataReaderToDictionary(
+			IDataReader     reader,
+			IDictionary     destDictionary,
+			MapIndex        index,
+			Type            destObjectType,
+			params object[] parameters)
+		{
+			MapSourceListToDestinationList(
+				CreateDataReaderListMapper(reader),
+				CreateDictionaryListMapper(destDictionary, index, GetObjectMapper(destObjectType)),
+				parameters);
+
+			return destDictionary;
+		}
+
+		public IDictionary MapDataReaderToDictionary(
+			IDataReader     reader,
+			MapIndex        index,
+			Type            destObjectType,
+			params object[] parameters)
+		{
+			IDictionary destDictionary = new Dictionary<object,object>();
+
+			MapSourceListToDestinationList(
+				CreateDataReaderListMapper(reader),
+				CreateDictionaryListMapper(destDictionary, index, GetObjectMapper(destObjectType)),
+				parameters);
+
+			return destDictionary;
+		}
+
+		public IDictionary<CompoundValue,T> MapDataReaderToDictionary<T>(
+			IDataReader                  reader,
+			IDictionary<CompoundValue,T> destDictionary,
+			MapIndex                     index,
+			Type                         destObjectType,
+			params object[]              parameters)
+		{
+			MapSourceListToDestinationList(
+				CreateDataReaderListMapper(reader),
+				CreateDictionaryListMapper(destDictionary, index, GetObjectMapper(destObjectType)),
+				parameters);
+
+			return destDictionary;
+		}
+
+		public IDictionary<CompoundValue,T> MapDataReaderToDictionary<T>(
+			IDataReader                  reader,
+			IDictionary<CompoundValue,T> destDictionary,
+			MapIndex                     index,
+			params object[]              parameters)
+		{
+			MapSourceListToDestinationList(
+				CreateDataReaderListMapper(reader),
+				CreateDictionaryListMapper(destDictionary, index, GetObjectMapper(typeof(T))),
+				parameters);
+
+			return destDictionary;
+		}
+
+		public Dictionary<CompoundValue,T> MapDataReaderToDictionary<T>(
+			IDataReader     reader,
+			MapIndex        index,
+			params object[] parameters)
+		{
+			Dictionary<CompoundValue,T> destDictionary = new Dictionary<CompoundValue,T>();
+
+			MapSourceListToDestinationList(
+				CreateDataReaderListMapper   (reader),
+				CreateDictionaryListMapper<T>(destDictionary, index, GetObjectMapper(typeof(T))),
+				parameters);
+
+			return destDictionary;
+		}
+
+		#endregion
+
+		#endregion
+
+		#region Dictionary
+
+		#region MapDictionaryToList
+
+		public IList MapDictionaryToList(
+			IDictionary     sourceDictionary,
+			IList           destList,
+			Type            destObjectType,
+			params object[] parameters)
+		{
+			if (sourceDictionary == null) throw new ArgumentNullException("sourceDictionary");
+
+			MapSourceListToDestinationList(
+				CreateEnumeratorMapper(sourceDictionary.Values.GetEnumerator()),
+				CreateObjectListMapper(destList, GetObjectMapper(destObjectType)),
+				parameters);
+
+			return destList;
+		}
+
+		public IList MapDictionaryToList(
+			IDictionary     sourceDictionary,
+			Type            destObjectType,
+			params object[] parameters)
+		{
+			if (sourceDictionary == null) throw new ArgumentNullException("sourceDictionary");
+
+			IList destList = new List<object>();
+
+			MapSourceListToDestinationList(
+				CreateEnumeratorMapper(sourceDictionary.Values.GetEnumerator()),
+				CreateObjectListMapper(destList, GetObjectMapper(destObjectType)),
+				parameters);
+
+			return destList;
+		}
+
+		public List<T> MapDictionaryToList<T>(
+			IDictionary     sourceDictionary,
+			List<T>         destList,
+			params object[] parameters)
+		{
+			if (sourceDictionary == null) throw new ArgumentNullException("sourceDictionary");
+
+			MapSourceListToDestinationList(
+				CreateEnumeratorMapper(sourceDictionary.Values.GetEnumerator()),
+				CreateObjectListMapper(destList, GetObjectMapper(typeof(T))),
+				parameters);
+
+			return destList;
+		}
+
+		public List<T> MapDictionaryToList<T>(
+			IDictionary     sourceDictionary,
+			params object[] parameters)
+		{
+			if (sourceDictionary == null) throw new ArgumentNullException("sourceDictionary");
+
+			List<T> destList = new List<T>();
+
+			MapSourceListToDestinationList(
+				CreateEnumeratorMapper(sourceDictionary.Values.GetEnumerator()),
+				CreateObjectListMapper(destList, GetObjectMapper(typeof(T))),
+				parameters);
+
+			return destList;
+		}
+
+		#endregion
+
+		#region MapDictionaryToDataTable
+
+#if !SILVERLIGHT
+
+		public DataTable MapDictionaryToDataTable(
+			IDictionary sourceDictionary,
+			DataTable   destTable)
+		{
+			if (sourceDictionary == null) throw new ArgumentNullException("sourceDictionary");
+
+			MapSourceListToDestinationList(
+				CreateEnumeratorMapper(sourceDictionary.Values.GetEnumerator()),
+				CreateDataTableMapper (destTable, DataRowVersion.Default),
+				null);
+
+			return destTable;
+		}
+
+		[SuppressMessage("Microsoft.Globalization", "CA1306:SetLocaleForDataTypes")]
+		public DataTable MapDictionaryToDataTable(IDictionary sourceDictionary)
+		{
+			if (sourceDictionary == null) throw new ArgumentNullException("sourceDictionary");
+
+			DataTable destTable = new DataTable();
+
+			MapSourceListToDestinationList(
+				CreateEnumeratorMapper(sourceDictionary.Values.GetEnumerator()),
+				CreateDataTableMapper (destTable, DataRowVersion.Default),
+				null);
+
+			return destTable;
+		}
+
+#endif
+
+		#endregion
+
+		#region MapDictionaryToDictionary
+
+		public IDictionary MapDictionaryToDictionary(
+			IDictionary          sourceDictionary,
+			IDictionary          destDictionary,
+			NameOrIndexParameter keyFieldNameOrIndex,
+			Type                 destObjectType,
+			params object[]      parameters)
+		{
+			if (sourceDictionary == null) throw new ArgumentNullException("sourceDictionary");
+
+			MapSourceListToDestinationList(
+				CreateEnumeratorMapper    (sourceDictionary.Values.GetEnumerator()),
+				CreateDictionaryListMapper(destDictionary, keyFieldNameOrIndex, GetObjectMapper(destObjectType)),
+				parameters);
+
+			return destDictionary;
+		}
+
+		public IDictionary MapDictionaryToDictionary(
+			IDictionary          sourceDictionary,
+			NameOrIndexParameter keyFieldNameOrIndex,
+			Type                 destObjectType,
+			params object[]      parameters)
+		{
+			if (sourceDictionary == null) throw new ArgumentNullException("sourceDictionary");
+
+			IDictionary dest = new Dictionary<object,object>();
+
+			MapSourceListToDestinationList(
+				CreateEnumeratorMapper    (sourceDictionary.Values.GetEnumerator()),
+				CreateDictionaryListMapper(dest, keyFieldNameOrIndex, GetObjectMapper(destObjectType)),
+				parameters);
+
+			return dest;
+		}
+
+		public IDictionary<TK,T> MapDictionaryToDictionary<TK,T>(
+			IDictionary          sourceDictionary,
+			IDictionary<TK,T>     destDictionary,
+			NameOrIndexParameter keyFieldNameOrIndex,
+			params object[]      parameters)
+		{
+			if (sourceDictionary == null) throw new ArgumentNullException("sourceDictionary");
+
+			MapSourceListToDestinationList(
+				CreateEnumeratorMapper         (sourceDictionary.Values.GetEnumerator()),
+				CreateDictionaryListMapper<TK,T>(destDictionary, keyFieldNameOrIndex, GetObjectMapper(typeof(T))),
+				parameters);
+
+			return destDictionary;
+		}
+
+		public Dictionary<TK,T> MapDictionaryToDictionary<TK,T>(
+			IDictionary          sourceDictionary,
+			NameOrIndexParameter keyFieldNameOrIndex,
+			params object[]      parameters)
+		{
+			if (sourceDictionary == null) throw new ArgumentNullException("sourceDictionary");
+
+			Dictionary<TK,T> dest = new Dictionary<TK,T>();
+
+			MapSourceListToDestinationList(
+				CreateEnumeratorMapper         (sourceDictionary.Values.GetEnumerator()),
+				CreateDictionaryListMapper<TK,T>(dest, keyFieldNameOrIndex, GetObjectMapper(typeof(T))),
+				parameters);
+
+			return dest;
+		}
+
+		#endregion
+
+		#region MapDictionaryToDictionary (Index)
+
+		public IDictionary MapDictionaryToDictionary(
+			IDictionary     sourceDictionary,
+			IDictionary     destDictionary,
+			MapIndex        index,
+			Type            destObjectType,
+			params object[] parameters)
+		{
+			if (sourceDictionary == null) throw new ArgumentNullException("sourceDictionary");
+
+			MapSourceListToDestinationList(
+				CreateEnumeratorMapper    (sourceDictionary.Values.GetEnumerator()),
+				CreateDictionaryListMapper(destDictionary, index, GetObjectMapper(destObjectType)),
+				parameters);
+
+			return destDictionary;
+		}
+
+		public IDictionary MapDictionaryToDictionary(
+			IDictionary     sourceDictionary,
+			MapIndex        index,
+			Type            destObjectType,
+			params object[] parameters)
+		{
+			if (sourceDictionary == null) throw new ArgumentNullException("sourceDictionary");
+
+			IDictionary destDictionary = new Dictionary<object,object>();
+
+			MapSourceListToDestinationList(
+				CreateEnumeratorMapper    (sourceDictionary.Values.GetEnumerator()),
+				CreateDictionaryListMapper(destDictionary, index, GetObjectMapper(destObjectType)),
+				parameters);
+
+			return destDictionary;
+		}
+
+		public IDictionary<CompoundValue,T> MapDictionaryToDictionary<T>(
+			IDictionary                  sourceDictionary,
+			IDictionary<CompoundValue,T> destDictionary,
+			MapIndex                     index,
+			params object[]              parameters)
+		{
+			if (sourceDictionary == null) throw new ArgumentNullException("sourceDictionary");
+
+			MapSourceListToDestinationList(
+				CreateEnumeratorMapper       (sourceDictionary.Values.GetEnumerator()),
+				CreateDictionaryListMapper<T>(destDictionary, index, GetObjectMapper(typeof(T))),
+				parameters);
+
+			return destDictionary;
+		}
+
+		public Dictionary<CompoundValue,T> MapDictionaryToDictionary<T>(
+			IDictionary     sourceDictionary,
+			MapIndex        index,
+			params object[] parameters)
+		{
+			if (sourceDictionary == null) throw new ArgumentNullException("sourceDictionary");
+
+			Dictionary<CompoundValue,T> destDictionary = new Dictionary<CompoundValue,T>();
+
+			MapSourceListToDestinationList(
+				CreateEnumeratorMapper       (sourceDictionary.Values.GetEnumerator()),
+				CreateDictionaryListMapper<T>(destDictionary, index, GetObjectMapper(typeof(T))),
+				parameters);
+
+			return destDictionary;
+		}
+
+		#endregion
+
+		#endregion
+
+		#region MapToResultSet
+
+		public void MapResultSets(MapResultSet[] resultSets)
+		{
+			var initTable = new Dictionary<object,object>();
+			var context   = new InitContext();
+
+			object lastContainer = null;
+
+			context.MappingSchema = this;
+
+			try
+			{
+				PrepareRelarions(resultSets);
+
+				// Map relations.
+				//
+				foreach (MapResultSet rs in resultSets)
+				{
+					if (rs.Relations == null)
+						continue;
+
+					ObjectMapper masterMapper = GetObjectMapper(rs.ObjectType);
+
+					foreach (MapRelation r in rs.Relations)
+					{
+						MemberAccessor ma = masterMapper.TypeAccessor[r.ContainerName];
+
+						if (ma == null)
+							throw new MappingException(string.Format(Resources.MapIndex_BadField,
+								masterMapper.TypeAccessor.OriginalType.Name, r.ContainerName));
+
+						// Map.
+						//
+						var slave        = r.SlaveResultSet;
+						var slaveMapper  = GetObjectMapper(r.SlaveResultSet.ObjectType);
+						var indexedLists = rs.GetIndex(this, r.MasterIndex);
+
+						foreach (object o in slave.List)
+						{
+							object key = r.SlaveIndex.GetValueOrIndex(slaveMapper, o);
+
+							if (IsNull(key))
+								continue;
+
+							IList masterList;
+
+							if (!indexedLists.TryGetValue(key, out masterList))
+								continue;
+
+							foreach (object master in masterList)
+							{
+								ISupportMapping msm = master as ISupportMapping;
+
+								if (msm != null)
+								{
+									if (initTable.ContainsKey(master) == false)
+									{
+										msm.BeginMapping(context);
+										initTable.Add(master, msm);
+									}
+								}
+
+								object container = ma.GetValue(master);
+
+								if (container is IList)
+								{
+									if (lastContainer != container)
+									{
+										lastContainer = container;
+
+										ISupportMapping sm = container as ISupportMapping;
+
+										if (sm != null)
+										{
+											if (initTable.ContainsKey(container) == false)
+											{
+												sm.BeginMapping(context);
+												initTable[container] = sm;
+											}
+										}
+									}
+
+									((IList)container).Add(o);
+								}
+								else
+								{
+									ma.SetValue(master, o);
+								}
+							}
+						}
+					}
+				}
+			}
+			finally
+			{
+				foreach (ISupportMapping si in initTable.Values)
+					si.EndMapping(context);
+			}
+		}
+
+		public void MapDataReaderToResultSet(
+			IDataReader    reader,
+			MapResultSet[] resultSets)
+		{
+			if (reader == null) throw new ArgumentNullException("reader");
+
+			foreach (MapResultSet rs in resultSets)
+			{
+				MapDataReaderToList(reader, rs.List, rs.ObjectType, rs.Parameters);
+
+				if (reader.NextResult() == false)
+					break;
+			}
+
+			MapResultSets(resultSets);
+		}
+
+#if !SILVERLIGHT
+
+		public void MapDataSetToResultSet(
+			DataSet        dataSet,
+			MapResultSet[] resultSets)
+		{
+			for (int i = 0; i < resultSets.Length && i < dataSet.Tables.Count; i++)
+			{
+				MapResultSet rs = resultSets[i];
+
+				MapDataTableToList(dataSet.Tables[i], rs.List, rs.ObjectType, rs.Parameters);
+			}
+
+			MapResultSets(resultSets);
+		}
+
+#endif
+
+		public MapResultSet[] Clone(MapResultSet[] resultSets)
+		{
+			MapResultSet[] output = new MapResultSet[resultSets.Length];
+
+			for (int i = 0; i < resultSets.Length; i++)
+				output[i] = new MapResultSet(resultSets[i]);
+
+			return output;
+		}
+
+		private static int GetResultCount(MapNextResult[] nextResults)
+		{
+			int n = nextResults.Length;
+
+			foreach (MapNextResult nr in nextResults)
+				n += GetResultCount(nr.NextResults);
+
+			return n;
+		}
+
+		private static int GetResultSets(
+			int             current,
+			MapResultSet[]  output,
+			MapResultSet    master,
+			MapNextResult[] nextResults)
+		{
+			foreach (MapNextResult nr in nextResults)
+			{
+				output[current] = new MapResultSet(nr.ObjectType);
+
+				master.AddRelation(output[current], nr.SlaveIndex, nr.MasterIndex, nr.ContainerName);
+
+				current += GetResultSets(current + 1, output, output[current], nr.NextResults);
+			}
+
+			return current;
+		}
+
+		public MapResultSet[] ConvertToResultSet(
+			Type                   masterType,
+			params MapNextResult[] nextResults)
+		{
+			MapResultSet[] output = new MapResultSet[1 + GetResultCount(nextResults)];
+
+			output[0] = new MapResultSet(masterType);
+
+			GetResultSets(1, output, output[0], nextResults);
+
+			return output;
+		}
+
+		private void PrepareRelarions(params MapResultSet[] sets)
+		{
+			foreach (MapResultSet masterSet in sets)
+			{
+				if (masterSet.Relations != null)
+					continue;
+
+				foreach (MapResultSet slaveSet in sets)
+				{
+					bool isSet;
+
+					List<MapRelationBase> relations
+						= MetadataProvider.GetRelations(this, Extensions, masterSet.ObjectType, slaveSet.ObjectType, out isSet);
+
+					if (!isSet)
+						continue;
+
+					foreach (MapRelationBase relation in relations)
+						masterSet.AddRelation(slaveSet, relation);
+				}
+			}
+		}
+
+		#endregion
+
+		#region GetObjectMapper
+
+		public Func<TSource,TDest> GetObjectMapper<TSource,TDest>()
+		{
+			return new ExpressionMapper<TSource,TDest>(this)
+			{
+				IncludeComplexMapping = Common.Configuration.ExpressionMapper.IncludeComplexMapping
+			}.GetMapper();
+		}
+
+		public Func<TSource,TDest> GetObjectMapper<TSource,TDest>(bool deepCopy)
+		{
+			return new ExpressionMapper<TSource,TDest>(this)
+			{
+				DeepCopy              = deepCopy,
+				IncludeComplexMapping = Common.Configuration.ExpressionMapper.IncludeComplexMapping
+			}.GetMapper();
+		}
+
+		public Func<TSource,TDest> GetObjectMapper<TSource,TDest>(bool deepCopy, bool includeComplexMapping)
+		{
+			return new ExpressionMapper<TSource,TDest>(this)
+			{
+				DeepCopy              = deepCopy,
+				IncludeComplexMapping = includeComplexMapping
+			}.GetMapper();
+		}
+
+		#endregion
+
+		#region ConvertParameterValue
+
+		public virtual object ConvertParameterValue(object value, Type systemType)
+		{
+			return value;
+		}
+
+		#endregion        
+	}
+}