PageRenderTime 70ms CodeModel.GetById 4ms app.highlight 51ms RepoModel.GetById 1ms app.codeStats 1ms

/Source/Mapping/MappingSchema.cs

https://github.com/MaceWindu/bltoolkit
C# | 3891 lines | 3042 code | 814 blank | 35 comment | 503 complexity | efa4f7472e8e0586a116fbdb3860857a MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1using System;
   2using System.Collections;
   3using System.Collections.Generic;
   4using System.Data;
   5using System.Data.Linq;
   6using System.Data.SqlTypes;
   7using System.Diagnostics;
   8using System.Linq;
   9using System.IO;
  10using System.Reflection;
  11using System.Diagnostics.CodeAnalysis;
  12using System.Threading;
  13using System.Xml;
  14
  15#if !SILVERLIGHT
  16using System.Xml.Linq;
  17#endif
  18
  19using BLToolkit.Common;
  20using BLToolkit.Properties;
  21using BLToolkit.Reflection;
  22using BLToolkit.Reflection.Extension;
  23using BLToolkit.Reflection.MetadataProvider;
  24
  25#region ReSharper disable
  26// ReSharper disable SuggestUseVarKeywordEvident
  27// ReSharper disable UseObjectOrCollectionInitializer
  28// ReSharper disable SuggestUseVarKeywordEverywhere
  29// ReSharper disable RedundantTypeArgumentsOfMethod
  30#endregion
  31
  32using KeyValue = System.Collections.Generic.KeyValuePair<System.Type,System.Type>;
  33using Convert  = BLToolkit.Common.Convert;
  34
  35namespace BLToolkit.Mapping
  36{
  37	public class MappingSchema
  38	{
  39		#region Constructors
  40
  41		public MappingSchema()
  42		{
  43			InitNullValues();
  44		}
  45
  46		#endregion
  47
  48		#region ObjectMapper Support
  49
  50		private readonly Dictionary<Type,ObjectMapper> _mappers        = new Dictionary<Type,ObjectMapper>();
  51		private readonly Dictionary<Type,ObjectMapper> _pendingMappers = new Dictionary<Type,ObjectMapper>();
  52
  53		public ObjectMapper GetObjectMapper(Type type)
  54		{
  55			ObjectMapper om;
  56
  57			lock (_mappers)
  58			{
  59				if (_mappers.TryGetValue(type, out om))
  60					return om;
  61
  62				// This object mapper is initializing right now.
  63				// Note that only one thread can access to _pendingMappers each time.
  64				//
  65				if (_pendingMappers.TryGetValue(type, out om))
  66					return om;
  67
  68				om = CreateObjectMapper(type);
  69
  70				if (om == null)
  71					throw new MappingException(
  72						string.Format("Cannot create object mapper for the '{0}' type.", type.FullName));
  73
  74				_pendingMappers.Add(type, om);
  75
  76				try
  77				{
  78					om.Init(this, type);
  79				}
  80				finally
  81				{
  82					_pendingMappers.Remove(type);
  83				}
  84
  85				// Officially publish this ready to use object mapper.
  86				//
  87				SetObjectMapperInternal(type, om);
  88
  89				return om;
  90			}
  91		}
  92
  93		private void SetObjectMapperInternal(Type type, ObjectMapper om)
  94		{
  95			_mappers.Add(type, om);
  96
  97			if (type.IsAbstract)
  98			{
  99				var actualType = TypeAccessor.GetAccessor(type).Type;
 100
 101				if (!_mappers.ContainsKey(actualType))
 102					_mappers.Add(actualType, om);
 103			}
 104		}
 105
 106		public void SetObjectMapper(Type type, ObjectMapper om)
 107		{
 108			if (type == null) throw new ArgumentNullException("type");
 109
 110			lock (_mappers)
 111				SetObjectMapperInternal(type, om);
 112		}
 113
 114		protected virtual ObjectMapper CreateObjectMapper(Type type)
 115		{
 116			Attribute attr = TypeHelper.GetFirstAttribute(type, typeof(ObjectMapperAttribute));
 117			return attr == null? CreateObjectMapperInstance(type): ((ObjectMapperAttribute)attr).ObjectMapper;
 118		}
 119
 120		protected virtual ObjectMapper CreateObjectMapperInstance(Type type)
 121		{
 122			return new ObjectMapper();
 123		}
 124
 125		#endregion
 126
 127		#region MetadataProvider
 128
 129		private MetadataProviderBase _metadataProvider;
 130		public  MetadataProviderBase  MetadataProvider
 131		{
 132			[DebuggerStepThrough]
 133			get { return _metadataProvider ?? (_metadataProvider = CreateMetadataProvider()); }
 134			set { _metadataProvider = value; }
 135		}
 136
 137		protected virtual MetadataProviderBase CreateMetadataProvider()
 138		{
 139			return MetadataProviderBase.CreateProvider();
 140		}
 141
 142		#endregion
 143
 144		#region Public Members
 145
 146		public virtual ExtensionList Extensions { get; set; }
 147
 148		#endregion
 149
 150		#region Convert
 151
 152		public virtual void InitNullValues()
 153		{
 154			DefaultSByteNullValue          = (SByte)         GetNullValue(typeof(SByte));
 155			DefaultInt16NullValue          = (Int16)         GetNullValue(typeof(Int16));
 156			DefaultInt32NullValue          = (Int32)         GetNullValue(typeof(Int32));
 157			DefaultInt64NullValue          = (Int64)         GetNullValue(typeof(Int64));
 158			DefaultByteNullValue           = (Byte)          GetNullValue(typeof(Byte));
 159			DefaultUInt16NullValue         = (UInt16)        GetNullValue(typeof(UInt16));
 160			DefaultUInt32NullValue         = (UInt32)        GetNullValue(typeof(UInt32));
 161			DefaultUInt64NullValue         = (UInt64)        GetNullValue(typeof(UInt64));
 162			DefaultCharNullValue           = (Char)          GetNullValue(typeof(Char));
 163			DefaultSingleNullValue         = (Single)        GetNullValue(typeof(Single));
 164			DefaultDoubleNullValue         = (Double)        GetNullValue(typeof(Double));
 165			DefaultBooleanNullValue        = (Boolean)       GetNullValue(typeof(Boolean));
 166
 167			DefaultStringNullValue         = (String)        GetNullValue(typeof(String));
 168			DefaultDateTimeNullValue       = (DateTime)      GetNullValue(typeof(DateTime));
 169			DefaultDateTimeOffsetNullValue = (DateTimeOffset)GetNullValue(typeof(DateTimeOffset));
 170			DefaultLinqBinaryNullValue     = (Binary)        GetNullValue(typeof(Binary));
 171			DefaultDecimalNullValue        = (Decimal)       GetNullValue(typeof(Decimal));
 172			DefaultGuidNullValue           = (Guid)          GetNullValue(typeof(Guid));
 173			DefaultStreamNullValue         = (Stream)        GetNullValue(typeof(Stream));
 174#if !SILVERLIGHT
 175			DefaultXmlReaderNullValue      = (XmlReader)     GetNullValue(typeof(XmlReader));
 176			DefaultXmlDocumentNullValue    = (XmlDocument)   GetNullValue(typeof(XmlDocument));
 177            DefaultXElementNullValue       = (XElement)      GetNullValue(typeof(XElement));
 178#endif
 179		}
 180
 181		#region Primitive Types
 182
 183		[CLSCompliant(false)]
 184		public sbyte DefaultSByteNullValue { get; set; }
 185
 186		[CLSCompliant(false)]
 187		public virtual SByte ConvertToSByte(object value)
 188		{
 189			return
 190				value is SByte ? (SByte)value :
 191				value is Byte ? (SByte)(Byte)value :
 192				value == null ? DefaultSByteNullValue :
 193					Convert.ToSByte(value);
 194		}
 195
 196		public short DefaultInt16NullValue { get; set; }
 197
 198		public virtual Int16 ConvertToInt16(object value)
 199		{
 200			return
 201				value is Int16? (Int16)value:
 202				value == null || value is DBNull? DefaultInt16NullValue:
 203					Convert.ToInt16(value);
 204		}
 205
 206		public int DefaultInt32NullValue { get; set; }
 207
 208		public virtual Int32 ConvertToInt32(object value)
 209		{
 210			return
 211				value is Int32? (Int32)value:
 212				value == null || value is DBNull? DefaultInt32NullValue:
 213					Convert.ToInt32(value);
 214		}
 215
 216		public long DefaultInt64NullValue { get; set; }
 217
 218		public virtual Int64 ConvertToInt64(object value)
 219		{
 220			return
 221				value is Int64? (Int64)value:
 222				value == null || value is DBNull? DefaultInt64NullValue:
 223					Convert.ToInt64(value);
 224		}
 225
 226		public byte DefaultByteNullValue { get; set; }
 227
 228		public virtual Byte ConvertToByte(object value)
 229		{
 230			return
 231				value is Byte? (Byte)value:
 232				value == null || value is DBNull? DefaultByteNullValue:
 233					Convert.ToByte(value);
 234		}
 235
 236		[CLSCompliant(false)]
 237		public ushort DefaultUInt16NullValue { get; set; }
 238
 239		[CLSCompliant(false)]
 240		public virtual UInt16 ConvertToUInt16(object value)
 241		{
 242			return
 243				value is UInt16? (UInt16)value:
 244				value is Int16? (UInt16)(Int16)value:
 245				value == null || value is DBNull? DefaultUInt16NullValue:
 246					Convert.ToUInt16(value);
 247		}
 248
 249		[CLSCompliant(false)]
 250		public uint DefaultUInt32NullValue { get; set; }
 251
 252		[CLSCompliant(false)]
 253		public virtual UInt32 ConvertToUInt32(object value)
 254		{
 255			return
 256				value is UInt32? (UInt32)value:
 257				value is Int32? (UInt32)(Int32)value:
 258				value == null || value is DBNull? DefaultUInt32NullValue:
 259					Convert.ToUInt32(value);
 260		}
 261
 262		[CLSCompliant(false)]
 263		public ulong DefaultUInt64NullValue { get; set; }
 264
 265		[CLSCompliant(false)]
 266		public virtual UInt64 ConvertToUInt64(object value)
 267		{
 268			return
 269				value is UInt64? (UInt64)value:
 270				value is Int64? (UInt64)(Int64)value:
 271				value == null || value is DBNull? DefaultUInt64NullValue:
 272					Convert.ToUInt64(value);
 273		}
 274
 275		public char DefaultCharNullValue { get; set; }
 276
 277		public virtual Char ConvertToChar(object value)
 278		{
 279			return
 280				value is Char? (Char)value:
 281				value == null || value is DBNull? DefaultCharNullValue:
 282					Convert.ToChar(value);
 283		}
 284
 285		public float DefaultSingleNullValue { get; set; }
 286
 287		public virtual Single ConvertToSingle(object value)
 288		{
 289			return
 290				value is Single? (Single)value:
 291				value == null || value is DBNull? DefaultSingleNullValue:
 292					Convert.ToSingle(value);
 293		}
 294
 295		public double DefaultDoubleNullValue { get; set; }
 296
 297		public virtual Double ConvertToDouble(object value)
 298		{
 299			return
 300				value is Double? (Double)value:
 301				value == null || value is DBNull? DefaultDoubleNullValue:
 302					Convert.ToDouble(value);
 303		}
 304
 305		public bool DefaultBooleanNullValue { get; set; }
 306
 307		public virtual Boolean ConvertToBoolean(object value)
 308		{
 309			return
 310				value is Boolean? (Boolean)value:
 311				value == null || value is DBNull? DefaultBooleanNullValue:
 312					Convert.ToBoolean(value);
 313		}
 314
 315		#endregion
 316
 317		#region Simple Types
 318
 319		public string DefaultStringNullValue { get; set; }
 320
 321		public virtual String ConvertToString(object value)
 322		{
 323			return
 324				value is String? (String)value :
 325				value == null || value is DBNull? DefaultStringNullValue:
 326					Convert.ToString(value);
 327		}
 328
 329		public DateTime DefaultDateTimeNullValue { get; set; }
 330
 331		public virtual DateTime ConvertToDateTime(object value)
 332		{
 333			return
 334				value is DateTime? (DateTime)value:
 335				value == null || value is DBNull? DefaultDateTimeNullValue:
 336					Convert.ToDateTime(value);
 337		}
 338
 339		public virtual TimeSpan ConvertToTimeSpan(object value)
 340		{
 341			return ConvertToDateTime(value).TimeOfDay;
 342		}
 343
 344		public DateTimeOffset DefaultDateTimeOffsetNullValue { get; set; }
 345
 346		public virtual DateTimeOffset ConvertToDateTimeOffset(object value)
 347		{
 348			return
 349				value is DateTimeOffset? (DateTimeOffset)value:
 350				value == null || value is DBNull? DefaultDateTimeOffsetNullValue:
 351					Convert.ToDateTimeOffset(value);
 352		}
 353
 354		public Binary DefaultLinqBinaryNullValue { get; set; }
 355
 356		public virtual Binary ConvertToLinqBinary(object value)
 357		{
 358			return
 359				value is Binary ? (Binary)value:
 360				value is byte[] ? new Binary((byte[])value) : 
 361				value == null || value is DBNull? DefaultLinqBinaryNullValue:
 362					Convert.ToLinqBinary(value);
 363		}
 364
 365		public decimal DefaultDecimalNullValue { get; set; }
 366
 367		public virtual Decimal ConvertToDecimal(object value)
 368		{
 369			return
 370				value is Decimal? (Decimal)value:
 371				value == null || value is DBNull? DefaultDecimalNullValue:
 372					Convert.ToDecimal(value);
 373		}
 374
 375		public Guid DefaultGuidNullValue { get; set; }
 376
 377		public virtual Guid ConvertToGuid(object value)
 378		{
 379			return
 380				value is Guid? (Guid)value:
 381				value == null || value is DBNull? DefaultGuidNullValue:
 382					Convert.ToGuid(value);
 383		}
 384
 385		public Stream DefaultStreamNullValue { get; set; }
 386
 387		public virtual Stream ConvertToStream(object value)
 388		{
 389			return
 390				value is Stream? (Stream)value:
 391				value == null || value is DBNull? DefaultStreamNullValue:
 392					 Convert.ToStream(value);
 393		}
 394
 395#if !SILVERLIGHT
 396
 397		public XmlReader DefaultXmlReaderNullValue { get; set; }
 398
 399		public virtual XmlReader ConvertToXmlReader(object value)
 400		{
 401			return
 402				value is XmlReader? (XmlReader)value:
 403				value == null || value is DBNull? DefaultXmlReaderNullValue:
 404					Convert.ToXmlReader(value);
 405		}
 406
 407		public XmlDocument DefaultXmlDocumentNullValue { get; set; }
 408
 409		public virtual XmlDocument ConvertToXmlDocument(object value)
 410		{
 411			return
 412				value is XmlDocument? (XmlDocument)value:
 413				value == null || value is DBNull? DefaultXmlDocumentNullValue:
 414					Convert.ToXmlDocument(value);
 415		}
 416
 417        public XElement DefaultXElementNullValue { get; set; }
 418
 419        public virtual XElement ConvertToXElement(object value)
 420        {
 421            return
 422                value is XElement ? (XElement)value :
 423                value == null || value is DBNull ? DefaultXElementNullValue :
 424                    XElement.Parse(value.ToString());
 425        }
 426
 427#endif
 428
 429		public virtual byte[] ConvertToByteArray(object value)
 430		{
 431			return
 432				value is byte[]? (byte[])value:
 433				value == null || value is DBNull? null:
 434					Convert.ToByteArray(value);
 435		}
 436
 437		public virtual char[] ConvertToCharArray(object value)
 438		{
 439			return
 440				value is char[]? (char[])value:
 441				value == null || value is DBNull? null:
 442					Convert.ToCharArray(value);
 443		}
 444
 445		#endregion
 446
 447		#region Nullable Types
 448
 449		[CLSCompliant(false)]
 450		public virtual SByte? ConvertToNullableSByte(object value)
 451		{
 452			return
 453				value is SByte? (SByte?)value:
 454				value is Byte? (SByte?)(Byte)value:
 455				value == null || value is DBNull? null:
 456					Convert.ToNullableSByte(value);
 457		}
 458
 459		public virtual Int16? ConvertToNullableInt16(object value)
 460		{
 461			return
 462				value is Int16? (Int16?)value:
 463				value == null || value is DBNull? null:
 464					Convert.ToNullableInt16(value);
 465		}
 466
 467		public virtual Int32? ConvertToNullableInt32(object value)
 468		{
 469			return
 470				value is Int32? (Int32?)value:
 471				value == null || value is DBNull? null:
 472					Convert.ToNullableInt32(value);
 473		}
 474
 475		public virtual Int64? ConvertToNullableInt64(object value)
 476		{
 477			return
 478				value is Int64? (Int64?)value:
 479				value == null || value is DBNull? null:
 480					Convert.ToNullableInt64(value);
 481		}
 482
 483		public virtual Byte? ConvertToNullableByte(object value)
 484		{
 485			return
 486				value is Byte? (Byte?)value:
 487				value == null || value is DBNull? null:
 488					Convert.ToNullableByte(value);
 489		}
 490
 491		[CLSCompliant(false)]
 492		public virtual UInt16? ConvertToNullableUInt16(object value)
 493		{
 494			return
 495				value is UInt16? (UInt16?)value:
 496				value is Int16? (UInt16?)(Int16)value:
 497				value == null || value is DBNull? null:
 498					Convert.ToNullableUInt16(value);
 499		}
 500
 501		[CLSCompliant(false)]
 502		public virtual UInt32? ConvertToNullableUInt32(object value)
 503		{
 504			return
 505				value is UInt32? (UInt32?)value:
 506				value is Int32? (UInt32?)(Int32)value:
 507				value == null || value is DBNull? null:
 508					Convert.ToNullableUInt32(value);
 509		}
 510
 511		[CLSCompliant(false)]
 512		public virtual UInt64? ConvertToNullableUInt64(object value)
 513		{
 514			return
 515				value is UInt64? (UInt64?)value:
 516				value is Int64? (UInt64?)(Int64)value:
 517				value == null || value is DBNull? null:
 518					Convert.ToNullableUInt64(value);
 519		}
 520
 521		public virtual Char? ConvertToNullableChar(object value)
 522		{
 523			return
 524				value is Char? (Char?)value:
 525				value == null || value is DBNull? null:
 526					Convert.ToNullableChar(value);
 527		}
 528
 529		public virtual Double? ConvertToNullableDouble(object value)
 530		{
 531			return
 532				value is Double? (Double?)value:
 533				value == null || value is DBNull? null:
 534					Convert.ToNullableDouble(value);
 535		}
 536
 537		public virtual Single? ConvertToNullableSingle(object value)
 538		{
 539			return
 540				value is Single? (Single?)value:
 541				value == null || value is DBNull? null:
 542					Convert.ToNullableSingle(value);
 543		}
 544
 545		public virtual Boolean? ConvertToNullableBoolean(object value)
 546		{
 547			return
 548				value is Boolean? (Boolean?)value:
 549				value == null || value is DBNull? null:
 550					Convert.ToNullableBoolean(value);
 551		}
 552
 553		public virtual DateTime? ConvertToNullableDateTime(object value)
 554		{
 555			return
 556				value is DateTime? (DateTime?)value:
 557				value == null || value is DBNull? null:
 558					Convert.ToNullableDateTime(value);
 559		}
 560
 561		public virtual TimeSpan? ConvertToNullableTimeSpan(object value)
 562		{
 563			DateTime? dt = ConvertToNullableDateTime(value);
 564			return dt == null? null : (TimeSpan?)dt.Value.TimeOfDay;
 565		}
 566
 567		public virtual DateTimeOffset? ConvertToNullableDateTimeOffset(object value)
 568		{
 569			return
 570				value is DateTimeOffset? (DateTimeOffset?)value:
 571				value == null || value is DBNull? null:
 572					Convert.ToNullableDateTimeOffset(value);
 573		}
 574
 575		public virtual Decimal? ConvertToNullableDecimal(object value)
 576		{
 577			return
 578				value is Decimal? (Decimal?)value:
 579				value == null || value is DBNull? null:
 580					Convert.ToNullableDecimal(value);
 581		}
 582
 583		public virtual Guid? ConvertToNullableGuid(object value)
 584		{
 585			return
 586				value is Guid? (Guid?)value:
 587				value == null || value is DBNull? null:
 588					Convert.ToNullableGuid(value);
 589		}
 590
 591		#endregion
 592
 593		#region SqlTypes
 594
 595#if !SILVERLIGHT
 596
 597		public virtual SqlByte ConvertToSqlByte(object value)
 598		{
 599			return
 600				value == null || value is DBNull? SqlByte.Null :
 601				value is SqlByte? (SqlByte)value:
 602					Convert.ToSqlByte(value);
 603		}
 604
 605		public virtual SqlInt16 ConvertToSqlInt16(object value)
 606		{
 607			return
 608				value == null || value is DBNull? SqlInt16.Null:
 609				value is SqlInt16? (SqlInt16)value:
 610					Convert.ToSqlInt16(value);
 611		}
 612
 613		public virtual SqlInt32 ConvertToSqlInt32(object value)
 614		{
 615			return
 616				value == null || value is DBNull? SqlInt32.Null:
 617				value is SqlInt32? (SqlInt32)value:
 618					Convert.ToSqlInt32(value);
 619		}
 620
 621		public virtual SqlInt64 ConvertToSqlInt64(object value)
 622		{
 623			return
 624				value == null || value is DBNull? SqlInt64.Null:
 625				value is SqlInt64? (SqlInt64)value:
 626					Convert.ToSqlInt64(value);
 627		}
 628
 629		public virtual SqlSingle ConvertToSqlSingle(object value)
 630		{
 631			return
 632				value == null || value is DBNull? SqlSingle.Null:
 633				value is SqlSingle? (SqlSingle)value:
 634					Convert.ToSqlSingle(value);
 635		}
 636
 637		public virtual SqlBoolean ConvertToSqlBoolean(object value)
 638		{
 639			return
 640				value == null || value is DBNull? SqlBoolean.Null:
 641				value is SqlBoolean? (SqlBoolean)value:
 642					Convert.ToSqlBoolean(value);
 643		}
 644
 645		public virtual SqlDouble ConvertToSqlDouble(object value)
 646		{
 647			return
 648				value == null || value is DBNull? SqlDouble.Null:
 649				value is SqlDouble? (SqlDouble)value:
 650					Convert.ToSqlDouble(value);
 651		}
 652
 653		public virtual SqlDateTime ConvertToSqlDateTime(object value)
 654		{
 655			return
 656				value == null || value is DBNull? SqlDateTime.Null:
 657				value is SqlDateTime? (SqlDateTime)value:
 658					Convert.ToSqlDateTime(value);
 659		}
 660
 661		public virtual SqlDecimal ConvertToSqlDecimal(object value)
 662		{
 663			return
 664				value == null || value is DBNull? SqlDecimal.Null:
 665				value is SqlDecimal? (SqlDecimal)value:
 666				value is SqlMoney?   ((SqlMoney)value).ToSqlDecimal():
 667					Convert.ToSqlDecimal(value);
 668		}
 669
 670		public virtual SqlMoney ConvertToSqlMoney(object value)
 671		{
 672			return
 673				value == null || value is DBNull? SqlMoney.Null:
 674				value is SqlMoney?   (SqlMoney)value:
 675				value is SqlDecimal? ((SqlDecimal)value).ToSqlMoney():
 676					Convert.ToSqlMoney(value);
 677		}
 678
 679		public virtual SqlString ConvertToSqlString(object value)
 680		{
 681			return
 682				value == null || value is DBNull? SqlString.Null:
 683				value is SqlString? (SqlString)value:
 684					Convert.ToSqlString(value);
 685		}
 686
 687		public virtual SqlBinary ConvertToSqlBinary(object value)
 688		{
 689			return
 690				value == null || value is DBNull? SqlBinary.Null:
 691				value is SqlBinary? (SqlBinary)value:
 692					Convert.ToSqlBinary(value);
 693		}
 694
 695		public virtual SqlGuid ConvertToSqlGuid(object value)
 696		{
 697			return
 698				value == null || value is DBNull? SqlGuid.Null:
 699				value is SqlGuid? (SqlGuid)value:
 700					Convert.ToSqlGuid(value);
 701		}
 702
 703		public virtual SqlBytes ConvertToSqlBytes(object value)
 704		{
 705			return
 706				value == null || value is DBNull? SqlBytes.Null:
 707				value is SqlBytes? (SqlBytes)value:
 708					Convert.ToSqlBytes(value);
 709		}
 710
 711		public virtual SqlChars ConvertToSqlChars(object value)
 712		{
 713			return
 714				value == null || value is DBNull? SqlChars.Null:
 715				value is SqlChars? (SqlChars)value:
 716					Convert.ToSqlChars(value);
 717		}
 718
 719		public virtual SqlXml ConvertToSqlXml(object value)
 720		{
 721			return
 722				value == null || value is DBNull? SqlXml.Null:
 723				value is SqlXml? (SqlXml)value:
 724					Convert.ToSqlXml(value);
 725		}
 726
 727#endif
 728
 729		#endregion
 730
 731		#region General case
 732
 733		public virtual T GetDefaultNullValue<T>()
 734		{
 735			switch (Type.GetTypeCode(typeof(T)))
 736			{
 737				case TypeCode.Boolean:  return (T)(object)DefaultBooleanNullValue;
 738				case TypeCode.Byte:     return (T)(object)DefaultByteNullValue;
 739				case TypeCode.Char:     return (T)(object)DefaultCharNullValue;
 740				case TypeCode.DateTime: return (T)(object)DefaultDateTimeNullValue;
 741				case TypeCode.Decimal:  return (T)(object)DefaultDecimalNullValue;
 742				case TypeCode.Double:   return (T)(object)DefaultDoubleNullValue;
 743				case TypeCode.Int16:    return (T)(object)DefaultInt16NullValue;
 744				case TypeCode.Int32:    return (T)(object)DefaultInt32NullValue;
 745				case TypeCode.Int64:    return (T)(object)DefaultInt64NullValue;
 746				case TypeCode.SByte:    return (T)(object)DefaultSByteNullValue;
 747				case TypeCode.Single:   return (T)(object)DefaultSingleNullValue;
 748				case TypeCode.String:   return (T)(object)DefaultStringNullValue;
 749				case TypeCode.UInt16:   return (T)(object)DefaultUInt16NullValue;
 750				case TypeCode.UInt32:   return (T)(object)DefaultUInt32NullValue;
 751				case TypeCode.UInt64:   return (T)(object)DefaultUInt64NullValue;
 752			}
 753
 754			if (typeof(Guid)           == typeof(T)) return (T)(object)DefaultGuidNullValue;
 755			if (typeof(Stream)         == typeof(T)) return (T)(object)DefaultStreamNullValue;
 756#if !SILVERLIGHT
 757			if (typeof(XmlReader)      == typeof(T)) return (T)(object)DefaultXmlReaderNullValue;
 758			if (typeof(XmlDocument)    == typeof(T)) return (T)(object)DefaultXmlDocumentNullValue;
 759            if (typeof(XElement)       == typeof(T)) return (T)(object)DefaultXElementNullValue;
 760#endif
 761			if (typeof(DateTimeOffset) == typeof(T)) return (T)(object)DefaultDateTimeOffsetNullValue;
 762
 763			return default(T);
 764		}
 765
 766		public virtual T ConvertTo<T,TP>(TP value)
 767		{
 768			return Equals(value, default(TP))?
 769				GetDefaultNullValue<T>():
 770				Convert<T,TP>.From(value);
 771		}
 772
 773		public virtual object ConvertChangeType(object value, Type conversionType)
 774		{
 775			return ConvertChangeType(value, conversionType, TypeHelper.IsNullable(conversionType));
 776		}
 777
 778		public virtual object ConvertChangeType(object value, Type conversionType, bool isNullable)
 779		{
 780			if (conversionType.IsArray)
 781			{
 782				if (null == value)
 783					return null;
 784				
 785				Type srcType = value.GetType();
 786
 787				if (srcType == conversionType)
 788					return value;
 789
 790				if (srcType.IsArray)
 791				{
 792					Type srcElementType = srcType.GetElementType();
 793					Type dstElementType = conversionType.GetElementType();
 794
 795					if (srcElementType.IsArray != dstElementType.IsArray
 796						|| (srcElementType.IsArray &&
 797							srcElementType.GetArrayRank() != dstElementType.GetArrayRank()))
 798					{
 799						throw new InvalidCastException(string.Format(
 800							Resources.MappingSchema_IncompatibleArrayTypes,
 801							srcType.FullName, conversionType.FullName));
 802					}
 803
 804					Array srcArray = (Array)value;
 805					Array dstArray;
 806
 807					int rank = srcArray.Rank;
 808
 809					if (rank == 1 && 0 == srcArray.GetLowerBound(0))
 810					{
 811						int arrayLength = srcArray.Length;
 812
 813						dstArray = Array.CreateInstance(dstElementType, arrayLength);
 814
 815						// Int32 is assignable from UInt32, SByte from Byte and so on.
 816						//
 817						if (dstElementType.IsAssignableFrom(srcElementType))
 818							Array.Copy(srcArray, dstArray, arrayLength);
 819						else
 820							for (int i = 0; i < arrayLength; ++i)
 821								dstArray.SetValue(ConvertChangeType(srcArray.GetValue(i), dstElementType, isNullable), i);
 822					}
 823					else
 824					{
 825#if SILVERLIGHT
 826						throw new InvalidOperationException();
 827#else
 828						var arrayLength = 1;
 829						var dimensions  = new int[rank];
 830						var indices     = new int[rank];
 831						var lbounds     = new int[rank];
 832
 833						for (int i = 0; i < rank; ++i)
 834						{
 835							arrayLength *= (dimensions[i] = srcArray.GetLength(i));
 836							lbounds[i] = srcArray.GetLowerBound(i);
 837						}
 838
 839						dstArray = Array.CreateInstance(dstElementType, dimensions, lbounds);
 840
 841						for (int i = 0; i < arrayLength; ++i)
 842						{
 843							var index = i;
 844
 845							for (var j = rank - 1; j >= 0; --j)
 846							{
 847								indices[j] = index % dimensions[j] + lbounds[j];
 848								index /= dimensions[j];
 849							}
 850
 851							dstArray.SetValue(ConvertChangeType(srcArray.GetValue(indices), dstElementType, isNullable), indices);
 852						}
 853
 854#endif
 855					}
 856
 857					return dstArray;
 858				}
 859			}
 860			else if (conversionType.IsEnum)
 861			{
 862				return MapValueToEnum(value, conversionType);
 863			}
 864
 865			if (isNullable)
 866			{
 867				if (TypeHelper.IsNullable(conversionType))
 868				{
 869					// Return a null reference or boxed not null value.
 870					//
 871					return value == null || value is DBNull? null:
 872						ConvertChangeType(value, conversionType.GetGenericArguments()[0]);
 873				}
 874
 875				Type type = conversionType.IsEnum? Enum.GetUnderlyingType(conversionType): conversionType;
 876
 877				switch (Type.GetTypeCode(type))
 878				{
 879					case TypeCode.Boolean:  return ConvertToNullableBoolean (value);
 880					case TypeCode.Byte:     return ConvertToNullableByte    (value);
 881					case TypeCode.Char:     return ConvertToNullableChar    (value);
 882					case TypeCode.DateTime: return ConvertToNullableDateTime(value);
 883					case TypeCode.Decimal:  return ConvertToNullableDecimal (value);
 884					case TypeCode.Double:   return ConvertToNullableDouble  (value);
 885					case TypeCode.Int16:    return ConvertToNullableInt16   (value);
 886					case TypeCode.Int32:    return ConvertToNullableInt32   (value);
 887					case TypeCode.Int64:    return ConvertToNullableInt64   (value);
 888					case TypeCode.SByte:    return ConvertToNullableSByte   (value);
 889					case TypeCode.Single:   return ConvertToNullableSingle  (value);
 890					case TypeCode.UInt16:   return ConvertToNullableUInt16  (value);
 891					case TypeCode.UInt32:   return ConvertToNullableUInt32  (value);
 892					case TypeCode.UInt64:   return ConvertToNullableUInt64  (value);
 893				}
 894
 895				if (typeof(Guid)           == conversionType) return ConvertToNullableGuid(value);
 896				if (typeof(DateTimeOffset) == conversionType) return ConvertToNullableDateTimeOffset(value);
 897				if (typeof(TimeSpan)       == conversionType) return ConvertToNullableTimeSpan(value);	
 898			}
 899
 900			switch (Type.GetTypeCode(conversionType))
 901			{
 902				case TypeCode.Boolean:  return ConvertToBoolean (value);
 903				case TypeCode.Byte:     return ConvertToByte    (value);
 904				case TypeCode.Char:     return ConvertToChar    (value);
 905				case TypeCode.DateTime: return ConvertToDateTime(value);
 906				case TypeCode.Decimal:  return ConvertToDecimal (value);
 907				case TypeCode.Double:   return ConvertToDouble  (value);
 908				case TypeCode.Int16:    return ConvertToInt16   (value);
 909				case TypeCode.Int32:    return ConvertToInt32   (value);
 910				case TypeCode.Int64:    return ConvertToInt64   (value);
 911				case TypeCode.SByte:    return ConvertToSByte   (value);
 912				case TypeCode.Single:   return ConvertToSingle  (value);
 913				case TypeCode.String:   return ConvertToString  (value);
 914				case TypeCode.UInt16:   return ConvertToUInt16  (value);
 915				case TypeCode.UInt32:   return ConvertToUInt32  (value);
 916				case TypeCode.UInt64:   return ConvertToUInt64  (value);
 917			}
 918
 919			if (typeof(Guid)           == conversionType) return ConvertToGuid          (value);
 920			if (typeof(Stream)         == conversionType) return ConvertToStream        (value);
 921#if !SILVERLIGHT
 922			if (typeof(XmlReader)      == conversionType) return ConvertToXmlReader     (value);
 923			if (typeof(XmlDocument)    == conversionType) return ConvertToXmlDocument   (value);
 924            if (typeof(XElement)       == conversionType) return ConvertToXElement      (value);
 925#endif
 926			if (typeof(byte[])         == conversionType) return ConvertToByteArray     (value);
 927			if (typeof(Binary)         == conversionType) return ConvertToLinqBinary    (value);
 928			if (typeof(DateTimeOffset) == conversionType) return ConvertToDateTimeOffset(value);
 929			if (typeof(char[])         == conversionType) return ConvertToCharArray     (value);
 930			if (typeof(TimeSpan)       == conversionType) return ConvertToTimeSpan      (value);
 931
 932#if !SILVERLIGHT
 933
 934			if (typeof(SqlInt32)       == conversionType) return ConvertToSqlInt32      (value);
 935			if (typeof(SqlString)      == conversionType) return ConvertToSqlString     (value);
 936			if (typeof(SqlDecimal)     == conversionType) return ConvertToSqlDecimal    (value);
 937			if (typeof(SqlDateTime)    == conversionType) return ConvertToSqlDateTime   (value);
 938			if (typeof(SqlBoolean)     == conversionType) return ConvertToSqlBoolean    (value);
 939			if (typeof(SqlMoney)       == conversionType) return ConvertToSqlMoney      (value);
 940			if (typeof(SqlGuid)        == conversionType) return ConvertToSqlGuid       (value);
 941			if (typeof(SqlDouble)      == conversionType) return ConvertToSqlDouble     (value);
 942			if (typeof(SqlByte)        == conversionType) return ConvertToSqlByte       (value);
 943			if (typeof(SqlInt16)       == conversionType) return ConvertToSqlInt16      (value);
 944			if (typeof(SqlInt64)       == conversionType) return ConvertToSqlInt64      (value);
 945			if (typeof(SqlSingle)      == conversionType) return ConvertToSqlSingle     (value);
 946			if (typeof(SqlBinary)      == conversionType) return ConvertToSqlBinary     (value);
 947			if (typeof(SqlBytes)       == conversionType) return ConvertToSqlBytes      (value);
 948			if (typeof(SqlChars)       == conversionType) return ConvertToSqlChars      (value);
 949			if (typeof(SqlXml)         == conversionType) return ConvertToSqlXml        (value);
 950
 951#endif
 952
 953			return System.Convert.ChangeType(value, conversionType, Thread.CurrentThread.CurrentCulture);
 954		}
 955
 956		#endregion
 957		
 958		#endregion
 959
 960		#region Factory Members
 961
 962		public virtual DataReaderMapper CreateDataReaderMapper(IDataReader dataReader)
 963		{
 964			return new DataReaderMapper(this, dataReader);
 965		}
 966
 967		public virtual DataReaderListMapper CreateDataReaderListMapper(IDataReader reader)
 968		{
 969			return new DataReaderListMapper(CreateDataReaderMapper(reader));
 970		}
 971
 972		public virtual DataReaderMapper CreateDataReaderMapper(
 973			IDataReader          dataReader,
 974			NameOrIndexParameter nameOrIndex)
 975		{
 976			return new ScalarDataReaderMapper(this, dataReader, nameOrIndex);
 977		}
 978
 979		public virtual DataReaderListMapper CreateDataReaderListMapper(
 980			IDataReader          reader,
 981			NameOrIndexParameter nameOrIndex)
 982		{
 983			return new DataReaderListMapper(CreateDataReaderMapper(reader, nameOrIndex));
 984		}
 985
 986#if !SILVERLIGHT
 987
 988		public virtual DataRowMapper CreateDataRowMapper(
 989			DataRow        row,
 990			DataRowVersion version)
 991		{
 992			return new DataRowMapper(row, version);
 993		}
 994
 995		public virtual DataTableMapper CreateDataTableMapper(
 996			DataTable      dataTable,
 997			DataRowVersion version)
 998		{
 999			return new DataTableMapper(dataTable, CreateDataRowMapper(null, version));
1000		}
1001
1002#endif
1003
1004		public virtual DictionaryMapper CreateDictionaryMapper(IDictionary dictionary)
1005		{
1006			return new DictionaryMapper(dictionary);
1007		}
1008
1009		public virtual DictionaryListMapper CreateDictionaryListMapper(
1010			IDictionary          dic,
1011			NameOrIndexParameter keyFieldNameOrIndex,
1012			ObjectMapper         objectMapper)
1013		{
1014			return new DictionaryListMapper(dic, keyFieldNameOrIndex, objectMapper);
1015		}
1016		
1017		public virtual DictionaryIndexListMapper CreateDictionaryListMapper(
1018			IDictionary  dic,
1019			MapIndex     index,
1020			ObjectMapper objectMapper)
1021		{
1022			return new DictionaryIndexListMapper(dic, index, objectMapper);
1023		}
1024
1025		public virtual DictionaryListMapper<TK,T> CreateDictionaryListMapper<TK,T>(
1026			IDictionary<TK,T>     dic,
1027			NameOrIndexParameter keyFieldNameOrIndex,
1028			ObjectMapper         objectMapper)
1029		{
1030			return new DictionaryListMapper<TK,T>(dic, keyFieldNameOrIndex, objectMapper);
1031		}
1032
1033		public virtual DictionaryIndexListMapper<T> CreateDictionaryListMapper<T>(
1034			IDictionary<CompoundValue,T> dic,
1035			MapIndex                     index,
1036			ObjectMapper                 objectMapper)
1037		{
1038			return new DictionaryIndexListMapper<T>(dic, index, objectMapper);
1039		}
1040
1041		public virtual EnumeratorMapper CreateEnumeratorMapper(IEnumerator enumerator)
1042		{
1043			return new EnumeratorMapper(enumerator);
1044		}
1045
1046		public virtual ObjectListMapper CreateObjectListMapper(IList list, ObjectMapper objectMapper)
1047		{
1048			return new ObjectListMapper(list, objectMapper);
1049		}
1050
1051		public virtual ScalarListMapper CreateScalarListMapper(IList list, Type type)
1052		{
1053			return new ScalarListMapper(list, type);
1054		}
1055
1056		public virtual SimpleDestinationListMapper CreateScalarDestinationListMapper(IList list, Type type)
1057		{
1058			return new SimpleDestinationListMapper(CreateScalarListMapper(list, type));
1059		}
1060
1061		public virtual SimpleSourceListMapper CreateScalarSourceListMapper(IList list, Type type)
1062		{
1063			return new SimpleSourceListMapper(CreateScalarListMapper(list, type));
1064		}
1065
1066		public virtual ScalarListMapper<T> CreateScalarListMapper<T>(IList<T> list)
1067		{
1068			return new ScalarListMapper<T>(this, list);
1069		}
1070
1071		public virtual SimpleDestinationListMapper CreateScalarDestinationListMapper<T>(IList<T> list)
1072		{
1073			return new SimpleDestinationListMapper(CreateScalarListMapper<T>(list));
1074		}
1075
1076		#endregion
1077
1078		#region GetNullValue
1079
1080		public virtual object GetNullValue(Type type)
1081		{
1082			return TypeAccessor.GetNullValue(type);
1083		}
1084
1085		public virtual bool IsNull(object value)
1086		{
1087			return TypeAccessor.IsNull(value);
1088		}
1089
1090		#endregion
1091
1092		#region GetMapValues
1093
1094		private readonly Dictionary<Type,MapValue[]> _mapValues = new Dictionary<Type,MapValue[]>();
1095
1096		public virtual MapValue[] GetMapValues([JetBrains.Annotations.NotNull] Type type)
1097		{
1098			if (type == null) throw new ArgumentNullException("type");
1099
1100			lock (_mapValues)
1101			{
1102				MapValue[] mapValues;
1103
1104				if (_mapValues.TryGetValue(type, out mapValues))
1105					return mapValues;
1106
1107				var  typeExt = TypeExtension.GetTypeExtension(type, Extensions);
1108				bool isSet;
1109
1110				mapValues = MetadataProvider.GetMapValues(typeExt, type, out isSet);
1111
1112				_mapValues.Add(type, mapValues);
1113
1114				return mapValues;
1115			}
1116		}
1117
1118		private readonly Dictionary<MemberAccessor, MapValue[]> _memberMapValues = new Dictionary<MemberAccessor, MapValue[]>();
1119
1120		private Type GetMapValueType(MapValue[] mapValues)
1121		{
1122			if (mapValues != null)
1123			{
1124				var value = mapValues.SelectMany(mv => mv.MapValues).FirstOrDefault();
1125				if (value != null)
1126				{
1127					return value.GetType();
1128				}
1129			}
1130			return null;
1131		}
1132
1133		public virtual MapValue[] GetMapValues([JetBrains.Annotations.NotNull] MemberAccessor memberAccessor)
1134		{
1135			if (memberAccessor == null) throw new ArgumentNullException("memberAccessor");
1136
1137			lock (_memberMapValues)
1138			{
1139				MapValue[] mapValues;
1140
1141				if (_memberMapValues.TryGetValue(memberAccessor, out mapValues))
1142					return mapValues;
1143
1144				var typeExt = TypeExtension.GetTypeExtension(memberAccessor.Type, Extensions);
1145				bool isSet;
1146
1147				mapValues = MetadataProvider.GetMapValues(typeExt, memberAccessor, out isSet);
1148
1149				_memberMapValues.Add(memberAccessor, mapValues);
1150
1151				return mapValues;
1152			}
1153		}
1154
1155		#endregion
1156
1157		#region GetDefaultValue
1158
1159		private readonly Dictionary<Type,object> _defaultValues = new Dictionary<Type,object>();
1160
1161		public virtual object GetDefaultValue([JetBrains.Annotations.NotNull] Type type)
1162		{
1163			if (type == null) throw new ArgumentNullException("type");
1164
1165			lock (_defaultValues)
1166			{
1167				object defaultValue;
1168
1169				if (_defaultValues.TryGetValue(type, out defaultValue))
1170					return defaultValue;
1171
1172				var  typeExt = TypeExtension.GetTypeExtension(type, Extensions);
1173				bool isSet;
1174
1175				defaultValue = MetadataProvider.GetDefaultValue(this, typeExt, type, out isSet);
1176
1177				_defaultValues.Add(type, defaultValue = TypeExtension.ChangeType(defaultValue, type));
1178
1179				return defaultValue;
1180			}
1181		}
1182
1183		#endregion
1184
1185		#region GetDataSource, GetDataDestination
1186
1187		[CLSCompliant(false)]
1188		public virtual IMapDataSource GetDataSource(object obj)
1189		{
1190			if (obj == null) throw new ArgumentNullException("obj");
1191
1192			if (obj is IMapDataSource)
1193				return (IMapDataSource)obj;
1194
1195			if (obj is IDataReader)
1196				return CreateDataReaderMapper((IDataReader)obj);
1197
1198#if !SILVERLIGHT
1199
1200			if (obj is DataRow)
1201				return CreateDataRowMapper((DataRow)obj, DataRowVersion.Default);
1202
1203			if (obj is DataRowView)
1204				return CreateDataRowMapper(
1205					((DataRowView)obj).Row,
1206					((DataRowView)obj).RowVersion);
1207
1208			if (obj is DataTable)
1209				return CreateDataRowMapper(((DataTable)(obj)).Rows[0], DataRowVersion.Default);
1210
1211#endif
1212
1213			if (obj is IDictionary)
1214				return CreateDictionaryMapper((IDictionary)obj);
1215
1216			return GetObjectMapper(obj.GetType());
1217		}
1218
1219		[CLSCompliant(false)]
1220		public virtual IMapDataDestination GetDataDestination(object obj)
1221		{
1222			if (obj == null) throw new ArgumentNullException("obj");
1223
1224			if (obj is IMapDataDestination)
1225				return (IMapDataDestination)obj;
1226
1227#if !SILVERLIGHT
1228
1229			if (obj is DataRow)
1230				return CreateDataRowMapper((DataRow)obj, DataRowVersion.Default);
1231
1232			if (obj is DataRowView)
1233				return CreateDataRowMapper(
1234					((DataRowView)obj).Row,
1235					((DataRowView)obj).RowVersion);
1236
1237			if (obj is DataTable)
1238			{
1239				DataTable dt = obj as DataTable;
1240				DataRow   dr = dt.NewRow();
1241
1242				dt.Rows.Add(dr);
1243
1244				return CreateDataRowMapper(dr, DataRowVersion.Default);
1245			}
1246
1247#endif
1248
1249			if (obj is IDictionary)
1250				return CreateDictionaryMapper((IDictionary)obj);
1251
1252			return GetObjectMapper(obj.GetType());
1253		}
1254
1255		[CLSCompliant(false)]
1256		public virtual IMapDataSourceList GetDataSourceList(object obj)
1257		{
1258			if (obj == null) throw new ArgumentNullException("obj");
1259
1260			if (obj is IMapDataSourceList)
1261				return (IMapDataSourceList)obj;
1262
1263			if (obj is IDataReader)
1264				return CreateDataReaderListMapper((IDataReader)obj);
1265
1266			Type type = obj.GetType().GetElementType();
1267
1268			return TypeHelper.IsScalar(type)?
1269				(IMapDataSourceList)CreateScalarSourceListMapper((IList)obj, type):
1270				CreateObjectListMapper((IList)obj, CreateObjectMapper(type));
1271		}
1272
1273		[CLSCompliant(false)]
1274		public virtual IMapDataDestinationList GetDataDestinationList(object obj)
1275		{
1276			if (obj == null) throw new ArgumentNullException("obj");
1277
1278			if (obj is IMapDataDestinationList)
1279				return (IMapDataDestinationList)obj;
1280
1281			Type type = obj.GetType().GetElementType();
1282
1283			return TypeHelper.IsScalar(type)?
1284				(IMapDataDestinationList)CreateScalarDestinationListMapper((IList)obj, type):
1285				CreateObjectListMapper((IList)obj, CreateObjectMapper(type));
1286		}
1287
1288		#endregion
1289
1290		#region ValueMapper
1291
1292		[CLSCompliant(false)]
1293		public virtual IValueMapper DefaultValueMapper
1294		{
1295			get { return ValueMapping.DefaultMapper; }
1296		}
1297
1298		internal readonly Dictionary<Type,IValueMapper>     SameTypeMappers      = new Dictionary<Type,IValueMapper>();
1299		internal readonly Dictionary<KeyValue,IValueMapper> DifferentTypeMappers = new Dictionary<KeyValue,IValueMapper>();
1300
1301		[CLSCompliant(false)]
1302		public void SetValueMapper(
1303			Type         sourceType,
1304			Type         destType,
1305			IValueMapper mapper)
1306		{
1307			if (sourceType == null) sourceType = typeof(object);
1308			if (destType   == null) destType   = typeof(object);
1309
1310			if (sourceType == destType)
1311			{
1312				lock (SameTypeMappers)
1313				{
1314					if (mapper == null)
1315						SameTypeMappers.Remove(sourceType);
1316					else if (SameTypeMappers.ContainsKey(sourceType))
1317						SameTypeMappers[sourceType] = mapper;
1318					else
1319						SameTypeMappers.Add(sourceType, mapper);
1320				}
1321			}
1322			else
1323			{
1324				KeyValue key = new KeyValue(sourceType, destType);
1325
1326				lock (DifferentTypeMappers)
1327				{
1328					if (mapper == null)
1329						DifferentTypeMappers.Remove(key);
1330					else if (DifferentTypeMappers.ContainsKey(key))
1331						DifferentTypeMappers[key] = mapper;
1332					else
1333						DifferentTypeMappers.Add(key, mapper);
1334				}
1335			}
1336		}
1337
1338		[CLSCompliant(false)]
1339		protected internal virtual IValueMapper GetValueMapper(
1340			Type sourceType,
1341			Type destType)
1342		{
1343			return ValueMapping.GetMapper(sourceType, destType);
1344		}
1345
1346		[CLSCompliant(false)]
1347		internal protected IValueMapper[] GetValueMappers(
1348			IMapDataSource      source,
1349			IMapDataDestination dest,
1350			int[]               index)
1351		{
1352			IValueMapper[] mappers = new IValueMapper[index.Length];
1353
1354			for (int i = 0; i < index.Length; i++)
1355			{
1356				int n = index[i];
1357
1358				if (n < 0)
1359					continue;
1360
1361				if (!source.SupportsTypedValues(i) || !dest.SupportsTypedValues(n))
1362				{
1363					mappers[i] = DefaultValueMapper;
1364					continue;
1365				}
1366
1367				Type sourceType = source.GetFieldType(i);
1368				Type destType   = dest.  GetFieldType(n);
1369
1370				if (sourceType == null) sourceType = typeof(object);
1371				if (destType   == null) destType   = typeof(object);
1372
1373				IValueMapper t;
1374
1375				if (sourceType == destType)
1376				{
1377					lock (SameTypeMappers)
1378						if (!SameTypeMappers.TryGetValue(sourceType, out t))
1379							SameTypeMappers.Add(sourceType, t = GetValueMapper(sourceType, destType));
1380				}
1381				else
1382				{
1383					var key = new KeyValue(sourceType, destType);
1384
1385					lock (DifferentTypeMappers)
1386						if (!DifferentTypeMappers.TryGetValue(key, out t))
1387								DifferentTypeMappers[key] = t = GetValueMapper(sourceType, destType);
1388				}
1389
1390				mappers[i] = t;
1391			}
1392
1393			return mappers;
1394		}
1395
1396		#endregion
1397
1398		#region Base Mapping
1399
1400		[CLSCompliant(false)]
1401		internal protected static int[] GetIndex(
1402			IMapDataSource      source,
1403			IMapDataDestination dest)
1404		{
1405			int   count = source.Count;
1406			int[] index = new int[count];
1407
1408			for (int i = 0; i < count; i++)
1409				index[i] = dest.GetOrdinal(source.GetName(i));
1410
1411			return index;
1412		}
1413
1414		[CLSCompliant(false), Obsolete]
1415		protected static void MapInternal(
1416			IMapDataSource      source, object sourceObject,
1417			IMapDataDestination dest,   object destObject,
1418			int[]               index)
1419		{
1420			for (int i = 0; i < index.Length; i++)
1421			{
1422				int n = index[i];
1423
1424				if (n >= 0)
1425					dest.SetValue(destObject, n, source.GetValue(sourceObject, i));
1426			}
1427		}
1428
1429		[CLSCompliant(false)]
1430		internal protected static void MapInternal(
1431			IMapDataSource      source, object sourceObject,
1432			IMapDataDestination dest,   object destObject,
1433			int[]               index,
1434			IValueMapper[]      mappers)
1435		{
1436			for (int i = 0; i < index.Length; i++)
1437			{
1438				int n = index[i];
1439
1440				if (n >= 0)
1441					mappers[i].Map(source, sourceObject, i, dest, destObject, n);
1442			}
1443		}
1444
1445		[CLSCompliant(false)]
1446		protected virtual void MapInternal(
1447			InitContext         initContext,
1448			IMapDataSource      source, object sourceObject, 
1449			IMapDataDestination dest,   object destObject,
1450			params object[]     parameters)
1451		{
1452			ISupportMapping smSource = sourceObject as ISupportMapping;
1453			ISupportMapping smDest   = destObject   as ISupportMapping;
1454
1455			if (smSource != null)
1456			{
1457				if (initContext == null)
1458				{
1459					initContext = new InitContext();
1460
1461					initContext.MappingSchema = this;
1462					initContext.DataSource    = source;
1463					initContext.SourceObject  = sourceObject;
1464					initContext.ObjectMapper  = dest as ObjectMapper;
1465					initContext.Parameters    = parameters;
1466				}
1467
1468				initContext.IsSource = true;
1469				smSource.BeginMapping(initContext);
1470				initContext.IsSource = false;
1471
1472				if (initContext.StopMapping)
1473					return;
1474			}
1475
1476			if (smDest != null)
1477			{
1478				if (initContext == null)
1479				{
1480					initContext = new InitContext();
1481
1482					initContext.MappingSchema = this;
1483					initContext.DataSource    = source;
1484					initContext.SourceObject  = sourceObject;
1485					initContext.ObjectMapper  = dest as ObjectMapper;
1486					initContext.Parameters    = parameters;
1487				}
1488
1489				smDest.BeginMapping(initContext);
1490
1491				if (initContext.StopMapping)
1492					return;
1493
1494				if (dest != initContext.ObjectMapper && initContext.ObjectMapper != null)
1495					dest = initContext.ObjectMapper;
1496			}
1497
1498			int[]          index   = GetIndex       (source, dest);
1499			IValueMapper[] mappers = GetValueMappers(source, dest, index);
1500
1501			MapInternal(source, sourceObject, dest, destObject, index, mappers);
1502
1503			if (smDest != null)
1504				smDest.EndMapping(initContext);
1505
1506			if (smSource != null)
1507			{
1508				initContext.IsSource = true;
1509				smSource.EndMapping(initContext);
1510				initContext.IsSource = false;
1511			}
1512		}
1513
1514		protected virtual object MapInternal(InitContext initContext)
1515		{
1516			object dest = initContext.ObjectMapper.CreateInstance(initContext);
1517
1518			if (initContext.StopMapping == false)
1519			{
1520				MapInternal(initContext,
1521					initContext.DataSource, initContext.SourceObject,
1522					initContext.ObjectMapper, dest,
1523					initContext.Parameters);
1524			}
1525
1526			return dest;
1527		}
1528
1529		[CLSCompliant(false)]
1530		public void MapSourceToDestination(
1531			IMapDataSource      source, object sourceObject, 
1532			IMapDataDestination dest,   object destObject,
1533			params object[]     parameters)
1534		{
1535			MapInternal(null, source, sourceObject, dest, destObject, parameters);
1536		}
1537
1538		public void MapSourceToDestination(
1539			object          sourceObject,
1540			object          destObject,
1541			params object[] parameters)
1542		{
1543			IMapDataSource      source = GetDataSource     (sourceObject);
1544			IMapDataDestination dest   = GetDataDestination(destObject);
1545
1546			MapInternal(null, source, sourceObject, dest, destObject, parameters);
1547		}
1548
1549		private static readonly ObjectMapper _nullMapper = new ObjectMapper();
1550
1551		private class MapInfo
1552		{
1553			public int[]          Index;
1554			public IValueMapper[] Mappers;
1555		}
1556
1557		[CLSCompliant(false)]
1558		public virtual void MapSourceListToDestinationList(
1559			IMapDataSourceList      dataSourceList,
1560			IMapDataDestinationList dataDestinationList,
1561			params object[]         parameters)
1562		{
1563			if (dataSourceList      == null) throw new ArgumentNullException("dataSourceList");
1564			if (dataDestinationList == null) throw new ArgumentNullException("dataDestinationList");
1565
1566			Dictionary<ObjectMapper,MapInfo> infos = new Dictionary<ObjectMapper,MapInfo>();
1567
1568			InitContext ctx = new InitContext();
1569
1570			ctx.MappingSchema = this;
1571			ctx.Parameters    = parameters;
1572
1573			dataSourceList.     InitMapping(ctx); if (ctx.StopMapping) return;
1574			dataDestinationList.InitMapping(ctx); if (ctx.StopMapping) return;
1575
1576			int[]               index   = null;
1577			IValueMapper[]      mappers = null;
1578			ObjectMapper        current = _nullMapper;
1579			IMapDataDestination dest    = dataDestinationList.GetDataDestination(ctx);
1580			ObjectMapper        om      = dest as ObjectMapper;
1581
1582			while (dataSourceList.SetNextDataSource(ctx))
1583			{
1584				ctx.ObjectMapper = om;
1585				ctx.StopMapping  = false;
1586
1587				object destObject = dataDestinationList.GetNextObject(ctx);
1588
1589				if (ctx.StopMapping) continue;
1590
1591				ISupportMapping smSource = ctx.SourceObject as ISupportMapping;
1592				ISupportMapping smDest   = destObject       as ISupportMapping;
1593
1594				if (smSource != null)
1595				{
1596					ctx.IsSource = true;
1597					smSource.BeginMapping(ctx);
1598					ctx.IsSource = false;
1599
1600					if (ctx.StopMapping)
1601						continue;
1602				}
1603
1604				if (smDest != null)
1605				{
1606					smDest.BeginMapping(ctx);
1607
1608					if (ctx.StopMapping)
1609						continue;
1610				}
1611
1612				IMapDataDestination currentDest = current ?? dest;
1613
1614				if (current != ctx.ObjectMapper)
1615				{
1616					current     = ctx.ObjectMapper;
1617					currentDest = current ?? dest;
1618
1619					if (current != null)
1620					{
1621						MapInfo info;
1622						if (!infos.TryGetValue(current, out info))
1623						{
1624							info = new MapInfo();
1625
1626							info.Index   = GetIndex(ctx.DataSource, currentDest);
1627							info.Mappers = GetValueMappers(ctx.DataSource, currentDest, info.Index);
1628
1629							infos.Add(current, info);
1630						}
1631
1632						index   = info.Index;
1633						mappers = info.Mappers;
1634					}
1635					else
1636					{
1637						index   = GetIndex(ctx.DataSource, currentDest);
1638						mappers = GetValueMappers(ctx.DataSource, currentDest, index);
1639					}
1640				}
1641
1642				MapInternal(
1643					ctx.DataSource,
1644					ctx.SourceObject,
1645					currentDest,
1646					destObject,
1647					index,
1648					mappers);
1649
1650				if (smDest != null)
1651					smDest.EndMapping(ctx);
1652
1653				if (smSource != null)
1654				{
1655					ctx.IsSource = true;
1656					smSource.EndMapping(ctx);
1657					ctx.IsSource = false;
1658				}
1659			}
1660
1661			dataDestinationList.EndMapping(ctx);
1662			dataSourceList.     EndMapping(ctx);
1663		}
1664
1665		#endregion
1666
1667		#region ValueToEnum, EnumToValue
1668
1669		[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
1670		public virtual object MapValueToEnum(object value, Type type)
1671		{
1672			if (value == null || value == DBNull.Value)
1673				return GetNullValue(type);
1674
1675			MapValue[] mapValues = GetMapValues(type);
1676
1677			var mapValueType = GetMapValueType(mapValues);
1678			if (mapValueType != null && value.GetType() != mapValueType)
1679			{
1680				value = ConvertChangeType(value, mapValueType);
1681			}
1682
1683			if (mapValues != null)
1684			{
1685				var comp = (IComparable)value;
1686
1687				foreach (MapValue mv in mapValues)
1688				foreach (object mapValue in mv.MapValues)
1689				{
1690					try
1691					{
1692						if (comp.CompareTo(mapValue) == 0)
1693							return mv.OrigValue;
1694					}
1695					catch (ArgumentException ex)
1696					{
1697						Debug.WriteLine(ex.Message, MethodBase.GetCurrentMethod().Name);
1698					}
1699				}
1700			}
1701
1702			InvalidCastException exInvalidCast = null;
1703
1704			var enumType = TypeHelper.UnwrapNullableType(type);
1705			try
1706			{
1707				value = ConvertChangeType(value, Enum.GetUnderlyingType(enumType));
1708
1709				if (Enum.IsDefined(enumType, value))
1710				{
1711					// Regular (known) enum field w/o explicit mapping defined.
1712					//
1713					return Enum.ToObject(enumT

Large files files are truncated, but you can click here to view the full file