PageRenderTime 78ms CodeModel.GetById 4ms app.highlight 60ms RepoModel.GetById 1ms app.codeStats 0ms

/Source/Mapping/MappingSchema.cs

https://gitlab.com/Chermyanin/bltoolkitsourcelearn
C# | 3854 lines | 3007 code | 812 blank | 35 comment | 498 complexity | d901190d2cd114a8961639a97c686c11 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				return Enum.ToObject(conversionType, ConvertChangeType(value, Enum.GetUnderlyingType(conversionType), false));
 862
 863			if (isNullable)
 864			{
 865				if (TypeHelper.IsNullable(conversionType))
 866				{
 867					// Return a null reference or boxed not null value.
 868					//
 869					return value == null || value is DBNull? null:
 870						ConvertChangeType(value, conversionType.GetGenericArguments()[0]);
 871				}
 872
 873				Type type = conversionType.IsEnum? Enum.GetUnderlyingType(conversionType): conversionType;
 874
 875				switch (Type.GetTypeCode(type))
 876				{
 877					case TypeCode.Boolean:  return ConvertToNullableBoolean (value);
 878					case TypeCode.Byte:     return ConvertToNullableByte    (value);
 879					case TypeCode.Char:     return ConvertToNullableChar    (value);
 880					case TypeCode.DateTime: return ConvertToNullableDateTime(value);
 881					case TypeCode.Decimal:  return ConvertToNullableDecimal (value);
 882					case TypeCode.Double:   return ConvertToNullableDouble  (value);
 883					case TypeCode.Int16:    return ConvertToNullableInt16   (value);
 884					case TypeCode.Int32:    return ConvertToNullableInt32   (value);
 885					case TypeCode.Int64:    return ConvertToNullableInt64   (value);
 886					case TypeCode.SByte:    return ConvertToNullableSByte   (value);
 887					case TypeCode.Single:   return ConvertToNullableSingle  (value);
 888					case TypeCode.UInt16:   return ConvertToNullableUInt16  (value);
 889					case TypeCode.UInt32:   return ConvertToNullableUInt32  (value);
 890					case TypeCode.UInt64:   return ConvertToNullableUInt64  (value);
 891				}
 892
 893				if (typeof(Guid)           == conversionType) return ConvertToNullableGuid(value);
 894				if (typeof(DateTimeOffset) == conversionType) return ConvertToNullableDateTimeOffset(value);
 895				if (typeof(TimeSpan)       == conversionType) return ConvertToNullableTimeSpan(value);	
 896			}
 897
 898			switch (Type.GetTypeCode(conversionType))
 899			{
 900				case TypeCode.Boolean:  return ConvertToBoolean (value);
 901				case TypeCode.Byte:     return ConvertToByte    (value);
 902				case TypeCode.Char:     return ConvertToChar    (value);
 903				case TypeCode.DateTime: return ConvertToDateTime(value);
 904				case TypeCode.Decimal:  return ConvertToDecimal (value);
 905				case TypeCode.Double:   return ConvertToDouble  (value);
 906				case TypeCode.Int16:    return ConvertToInt16   (value);
 907				case TypeCode.Int32:    return ConvertToInt32   (value);
 908				case TypeCode.Int64:    return ConvertToInt64   (value);
 909				case TypeCode.SByte:    return ConvertToSByte   (value);
 910				case TypeCode.Single:   return ConvertToSingle  (value);
 911				case TypeCode.String:   return ConvertToString  (value);
 912				case TypeCode.UInt16:   return ConvertToUInt16  (value);
 913				case TypeCode.UInt32:   return ConvertToUInt32  (value);
 914				case TypeCode.UInt64:   return ConvertToUInt64  (value);
 915			}
 916
 917			if (typeof(Guid)           == conversionType) return ConvertToGuid          (value);
 918			if (typeof(Stream)         == conversionType) return ConvertToStream        (value);
 919#if !SILVERLIGHT
 920			if (typeof(XmlReader)      == conversionType) return ConvertToXmlReader     (value);
 921			if (typeof(XmlDocument)    == conversionType) return ConvertToXmlDocument   (value);
 922            if (typeof(XElement)       == conversionType) return ConvertToXElement      (value);
 923#endif
 924			if (typeof(byte[])         == conversionType) return ConvertToByteArray     (value);
 925			if (typeof(Binary)         == conversionType) return ConvertToLinqBinary    (value);
 926			if (typeof(DateTimeOffset) == conversionType) return ConvertToDateTimeOffset(value);
 927			if (typeof(char[])         == conversionType) return ConvertToCharArray     (value);
 928			if (typeof(TimeSpan)       == conversionType) return ConvertToTimeSpan      (value);
 929
 930#if !SILVERLIGHT
 931
 932			if (typeof(SqlInt32)       == conversionType) return ConvertToSqlInt32      (value);
 933			if (typeof(SqlString)      == conversionType) return ConvertToSqlString     (value);
 934			if (typeof(SqlDecimal)     == conversionType) return ConvertToSqlDecimal    (value);
 935			if (typeof(SqlDateTime)    == conversionType) return ConvertToSqlDateTime   (value);
 936			if (typeof(SqlBoolean)     == conversionType) return ConvertToSqlBoolean    (value);
 937			if (typeof(SqlMoney)       == conversionType) return ConvertToSqlMoney      (value);
 938			if (typeof(SqlGuid)        == conversionType) return ConvertToSqlGuid       (value);
 939			if (typeof(SqlDouble)      == conversionType) return ConvertToSqlDouble     (value);
 940			if (typeof(SqlByte)        == conversionType) return ConvertToSqlByte       (value);
 941			if (typeof(SqlInt16)       == conversionType) return ConvertToSqlInt16      (value);
 942			if (typeof(SqlInt64)       == conversionType) return ConvertToSqlInt64      (value);
 943			if (typeof(SqlSingle)      == conversionType) return ConvertToSqlSingle     (value);
 944			if (typeof(SqlBinary)      == conversionType) return ConvertToSqlBinary     (value);
 945			if (typeof(SqlBytes)       == conversionType) return ConvertToSqlBytes      (value);
 946			if (typeof(SqlChars)       == conversionType) return ConvertToSqlChars      (value);
 947			if (typeof(SqlXml)         == conversionType) return ConvertToSqlXml        (value);
 948
 949#endif
 950
 951			return System.Convert.ChangeType(value, conversionType, Thread.CurrentThread.CurrentCulture);
 952		}
 953
 954		#endregion
 955		
 956		#endregion
 957
 958		#region Factory Members
 959
 960		public virtual DataReaderMapper CreateDataReaderMapper(IDataReader dataReader)
 961		{
 962			return new DataReaderMapper(this, dataReader);
 963		}
 964
 965		public virtual DataReaderListMapper CreateDataReaderListMapper(IDataReader reader)
 966		{
 967			return new DataReaderListMapper(CreateDataReaderMapper(reader));
 968		}
 969
 970		public virtual DataReaderMapper CreateDataReaderMapper(
 971			IDataReader          dataReader,
 972			NameOrIndexParameter nameOrIndex)
 973		{
 974			return new ScalarDataReaderMapper(this, dataReader, nameOrIndex);
 975		}
 976
 977		public virtual DataReaderListMapper CreateDataReaderListMapper(
 978			IDataReader          reader,
 979			NameOrIndexParameter nameOrIndex)
 980		{
 981			return new DataReaderListMapper(CreateDataReaderMapper(reader, nameOrIndex));
 982		}
 983
 984#if !SILVERLIGHT
 985
 986		public virtual DataRowMapper CreateDataRowMapper(
 987			DataRow        row,
 988			DataRowVersion version)
 989		{
 990			return new DataRowMapper(row, version);
 991		}
 992
 993		public virtual DataTableMapper CreateDataTableMapper(
 994			DataTable      dataTable,
 995			DataRowVersion version)
 996		{
 997			return new DataTableMapper(dataTable, CreateDataRowMapper(null, version));
 998		}
 999
1000#endif
1001
1002		public virtual DictionaryMapper CreateDictionaryMapper(IDictionary dictionary)
1003		{
1004			return new DictionaryMapper(dictionary);
1005		}
1006
1007		public virtual DictionaryListMapper CreateDictionaryListMapper(
1008			IDictionary          dic,
1009			NameOrIndexParameter keyFieldNameOrIndex,
1010			ObjectMapper         objectMapper)
1011		{
1012			return new DictionaryListMapper(dic, keyFieldNameOrIndex, objectMapper);
1013		}
1014		
1015		public virtual DictionaryIndexListMapper CreateDictionaryListMapper(
1016			IDictionary  dic,
1017			MapIndex     index,
1018			ObjectMapper objectMapper)
1019		{
1020			return new DictionaryIndexListMapper(dic, index, objectMapper);
1021		}
1022
1023		public virtual DictionaryListMapper<TK,T> CreateDictionaryListMapper<TK,T>(
1024			IDictionary<TK,T>     dic,
1025			NameOrIndexParameter keyFieldNameOrIndex,
1026			ObjectMapper         objectMapper)
1027		{
1028			return new DictionaryListMapper<TK,T>(dic, keyFieldNameOrIndex, objectMapper);
1029		}
1030
1031		public virtual DictionaryIndexListMapper<T> CreateDictionaryListMapper<T>(
1032			IDictionary<CompoundValue,T> dic,
1033			MapIndex                     index,
1034			ObjectMapper                 objectMapper)
1035		{
1036			return new DictionaryIndexListMapper<T>(dic, index, objectMapper);
1037		}
1038
1039		public virtual EnumeratorMapper CreateEnumeratorMapper(IEnumerator enumerator)
1040		{
1041			return new EnumeratorMapper(enumerator);
1042		}
1043
1044		public virtual ObjectListMapper CreateObjectListMapper(IList list, ObjectMapper objectMapper)
1045		{
1046			return new ObjectListMapper(list, objectMapper);
1047		}
1048
1049		public virtual ScalarListMapper CreateScalarListMapper(IList list, Type type)
1050		{
1051			return new ScalarListMapper(list, type);
1052		}
1053
1054		public virtual SimpleDestinationListMapper CreateScalarDestinationListMapper(IList list, Type type)
1055		{
1056			return new SimpleDestinationListMapper(CreateScalarListMapper(list, type));
1057		}
1058
1059		public virtual SimpleSourceListMapper CreateScalarSourceListMapper(IList list, Type type)
1060		{
1061			return new SimpleSourceListMapper(CreateScalarListMapper(list, type));
1062		}
1063
1064		public virtual ScalarListMapper<T> CreateScalarListMapper<T>(IList<T> list)
1065		{
1066			return new ScalarListMapper<T>(this, list);
1067		}
1068
1069		public virtual SimpleDestinationListMapper CreateScalarDestinationListMapper<T>(IList<T> list)
1070		{
1071			return new SimpleDestinationListMapper(CreateScalarListMapper<T>(list));
1072		}
1073
1074		#endregion
1075
1076		#region GetNullValue
1077
1078		public virtual object GetNullValue(Type type)
1079		{
1080			return TypeAccessor.GetNullValue(type);
1081		}
1082
1083		public virtual bool IsNull(object value)
1084		{
1085			return TypeAccessor.IsNull(value);
1086		}
1087
1088		#endregion
1089
1090		#region GetMapValues
1091
1092		private readonly Dictionary<Type,MapValue[]> _mapValues = new Dictionary<Type,MapValue[]>();
1093
1094		public virtual MapValue[] GetMapValues([JetBrains.Annotations.NotNull] Type type)
1095		{
1096			if (type == null) throw new ArgumentNullException("type");
1097
1098			lock (_mapValues)
1099			{
1100				MapValue[] mapValues;
1101
1102				if (_mapValues.TryGetValue(type, out mapValues))
1103					return mapValues;
1104
1105				var  typeExt = TypeExtension.GetTypeExtension(type, Extensions);
1106				bool isSet;
1107
1108				mapValues = MetadataProvider.GetMapValues(typeExt, type, out isSet);
1109
1110				_mapValues.Add(type, mapValues);
1111
1112				return mapValues;
1113			}
1114		}
1115
1116		private readonly Dictionary<MemberAccessor, MapValue[]> _memberMapValues = new Dictionary<MemberAccessor, MapValue[]>();
1117
1118		private Type GetMapValueType(MapValue[] mapValues)
1119		{
1120			if (mapValues != null)
1121			{
1122				var value = mapValues.SelectMany(mv => mv.MapValues).FirstOrDefault();
1123				if (value != null)
1124				{
1125					return value.GetType();
1126				}
1127			}
1128			return null;
1129		}
1130
1131		public virtual MapValue[] GetMapValues([JetBrains.Annotations.NotNull] MemberAccessor memberAccessor)
1132		{
1133			if (memberAccessor == null) throw new ArgumentNullException("memberAccessor");
1134
1135			lock (_memberMapValues)
1136			{
1137				MapValue[] mapValues;
1138
1139				if (_memberMapValues.TryGetValue(memberAccessor, out mapValues))
1140					return mapValues;
1141
1142				var typeExt = TypeExtension.GetTypeExtension(memberAccessor.Type, Extensions);
1143				bool isSet;
1144
1145				mapValues = MetadataProvider.GetMapValues(typeExt, memberAccessor, out isSet);
1146
1147				_memberMapValues.Add(memberAccessor, mapValues);
1148
1149				return mapValues;
1150			}
1151		}
1152
1153		#endregion
1154
1155		#region GetDefaultValue
1156
1157		private readonly Dictionary<Type,object> _defaultValues = new Dictionary<Type,object>();
1158
1159		public virtual object GetDefaultValue([JetBrains.Annotations.NotNull] Type type)
1160		{
1161			if (type == null) throw new ArgumentNullException("type");
1162
1163			lock (_defaultValues)
1164			{
1165				object defaultValue;
1166
1167				if (_defaultValues.TryGetValue(type, out defaultValue))
1168					return defaultValue;
1169
1170				var  typeExt = TypeExtension.GetTypeExtension(type, Extensions);
1171				bool isSet;
1172
1173				defaultValue = MetadataProvider.GetDefaultValue(this, typeExt, type, out isSet);
1174
1175				_defaultValues.Add(type, defaultValue = TypeExtension.ChangeType(defaultValue, type));
1176
1177				return defaultValue;
1178			}
1179		}
1180
1181		#endregion
1182
1183		#region GetDataSource, GetDataDestination
1184
1185		[CLSCompliant(false)]
1186		public virtual IMapDataSource GetDataSource(object obj)
1187		{
1188			if (obj == null) throw new ArgumentNullException("obj");
1189
1190			if (obj is IMapDataSource)
1191				return (IMapDataSource)obj;
1192
1193			if (obj is IDataReader)
1194				return CreateDataReaderMapper((IDataReader)obj);
1195
1196#if !SILVERLIGHT
1197
1198			if (obj is DataRow)
1199				return CreateDataRowMapper((DataRow)obj, DataRowVersion.Default);
1200
1201			if (obj is DataRowView)
1202				return CreateDataRowMapper(
1203					((DataRowView)obj).Row,
1204					((DataRowView)obj).RowVersion);
1205
1206			if (obj is DataTable)
1207				return CreateDataRowMapper(((DataTable)(obj)).Rows[0], DataRowVersion.Default);
1208
1209#endif
1210
1211			if (obj is IDictionary)
1212				return CreateDictionaryMapper((IDictionary)obj);
1213
1214			return GetObjectMapper(obj.GetType());
1215		}
1216
1217		[CLSCompliant(false)]
1218		public virtual IMapDataDestination GetDataDestination(object obj)
1219		{
1220			if (obj == null) throw new ArgumentNullException("obj");
1221
1222			if (obj is IMapDataDestination)
1223				return (IMapDataDestination)obj;
1224
1225#if !SILVERLIGHT
1226
1227			if (obj is DataRow)
1228				return CreateDataRowMapper((DataRow)obj, DataRowVersion.Default);
1229
1230			if (obj is DataRowView)
1231				return CreateDataRowMapper(
1232					((DataRowView)obj).Row,
1233					((DataRowView)obj).RowVersion);
1234
1235			if (obj is DataTable)
1236			{
1237				DataTable dt = obj as DataTable;
1238				DataRow   dr = dt.NewRow();
1239
1240				dt.Rows.Add(dr);
1241
1242				return CreateDataRowMapper(dr, DataRowVersion.Default);
1243			}
1244
1245#endif
1246
1247			if (obj is IDictionary)
1248				return CreateDictionaryMapper((IDictionary)obj);
1249
1250			return GetObjectMapper(obj.GetType());
1251		}
1252
1253		[CLSCompliant(false)]
1254		public virtual IMapDataSourceList GetDataSourceList(object obj)
1255		{
1256			if (obj == null) throw new ArgumentNullException("obj");
1257
1258			if (obj is IMapDataSourceList)
1259				return (IMapDataSourceList)obj;
1260
1261			if (obj is IDataReader)
1262				return CreateDataReaderListMapper((IDataReader)obj);
1263
1264			Type type = obj.GetType().GetElementType();
1265
1266			return TypeHelper.IsScalar(type)?
1267				(IMapDataSourceList)CreateScalarSourceListMapper((IList)obj, type):
1268				CreateObjectListMapper((IList)obj, CreateObjectMapper(type));
1269		}
1270
1271		[CLSCompliant(false)]
1272		public virtual IMapDataDestinationList GetDataDestinationList(object obj)
1273		{
1274			if (obj == null) throw new ArgumentNullException("obj");
1275
1276			if (obj is IMapDataDestinationList)
1277				return (IMapDataDestinationList)obj;
1278
1279			Type type = obj.GetType().GetElementType();
1280
1281			return TypeHelper.IsScalar(type)?
1282				(IMapDataDestinationList)CreateScalarDestinationListMapper((IList)obj, type):
1283				CreateObjectListMapper((IList)obj, CreateObjectMapper(type));
1284		}
1285
1286		#endregion
1287
1288		#region ValueMapper
1289
1290		[CLSCompliant(false)]
1291		public virtual IValueMapper DefaultValueMapper
1292		{
1293			get { return ValueMapping.DefaultMapper; }
1294		}
1295
1296		internal readonly Dictionary<Type,IValueMapper>     SameTypeMappers      = new Dictionary<Type,IValueMapper>();
1297		internal readonly Dictionary<KeyValue,IValueMapper> DifferentTypeMappers = new Dictionary<KeyValue,IValueMapper>();
1298
1299		[CLSCompliant(false)]
1300		public void SetValueMapper(
1301			Type         sourceType,
1302			Type         destType,
1303			IValueMapper mapper)
1304		{
1305			if (sourceType == null) sourceType = typeof(object);
1306			if (destType   == null) destType   = typeof(object);
1307
1308			if (sourceType == destType)
1309			{
1310				lock (SameTypeMappers)
1311				{
1312					if (mapper == null)
1313						SameTypeMappers.Remove(sourceType);
1314					else if (SameTypeMappers.ContainsKey(sourceType))
1315						SameTypeMappers[sourceType] = mapper;
1316					else
1317						SameTypeMappers.Add(sourceType, mapper);
1318				}
1319			}
1320			else
1321			{
1322				KeyValue key = new KeyValue(sourceType, destType);
1323
1324				lock (DifferentTypeMappers)
1325				{
1326					if (mapper == null)
1327						DifferentTypeMappers.Remove(key);
1328					else if (DifferentTypeMappers.ContainsKey(key))
1329						DifferentTypeMappers[key] = mapper;
1330					else
1331						DifferentTypeMappers.Add(key, mapper);
1332				}
1333			}
1334		}
1335
1336		[CLSCompliant(false)]
1337		protected internal virtual IValueMapper GetValueMapper(
1338			Type sourceType,
1339			Type destType)
1340		{
1341			return ValueMapping.GetMapper(sourceType, destType);
1342		}
1343
1344		[CLSCompliant(false)]
1345		internal protected IValueMapper[] GetValueMappers(
1346			IMapDataSource      source,
1347			IMapDataDestination dest,
1348			int[]               index)
1349		{
1350			IValueMapper[] mappers = new IValueMapper[index.Length];
1351
1352			for (int i = 0; i < index.Length; i++)
1353			{
1354				int n = index[i];
1355
1356				if (n < 0)
1357					continue;
1358
1359				if (!source.SupportsTypedValues(i) || !dest.SupportsTypedValues(n))
1360				{
1361					mappers[i] = DefaultValueMapper;
1362					continue;
1363				}
1364
1365				Type sourceType = source.GetFieldType(i);
1366				Type destType   = dest.  GetFieldType(n);
1367
1368				if (sourceType == null) sourceType = typeof(object);
1369				if (destType   == null) destType   = typeof(object);
1370
1371				IValueMapper t;
1372
1373				if (sourceType == destType)
1374				{
1375					lock (SameTypeMappers)
1376						if (!SameTypeMappers.TryGetValue(sourceType, out t))
1377							SameTypeMappers.Add(sourceType, t = GetValueMapper(sourceType, destType));
1378				}
1379				else
1380				{
1381					var key = new KeyValue(sourceType, destType);
1382
1383					lock (DifferentTypeMappers)
1384						if (!DifferentTypeMappers.TryGetValue(key, out t))
1385								DifferentTypeMappers[key] = t = GetValueMapper(sourceType, destType);
1386				}
1387
1388				mappers[i] = t;
1389			}
1390
1391			return mappers;
1392		}
1393
1394		#endregion
1395
1396		#region Base Mapping
1397
1398		[CLSCompliant(false)]
1399		internal protected static int[] GetIndex(
1400			IMapDataSource      source,
1401			IMapDataDestination dest)
1402		{
1403			int   count = source.Count;
1404			int[] index = new int[count];
1405
1406			for (int i = 0; i < count; i++)
1407				index[i] = dest.GetOrdinal(source.GetName(i));
1408
1409			return index;
1410		}
1411
1412		[CLSCompliant(false), Obsolete]
1413		protected static void MapInternal(
1414			IMapDataSource      source, object sourceObject,
1415			IMapDataDestination dest,   object destObject,
1416			int[]               index)
1417		{
1418			for (int i = 0; i < index.Length; i++)
1419			{
1420				int n = index[i];
1421
1422				if (n >= 0)
1423					dest.SetValue(destObject, n, source.GetValue(sourceObject, i));
1424			}
1425		}
1426
1427		[CLSCompliant(false)]
1428		internal protected static void MapInternal(
1429			IMapDataSource      source, object sourceObject,
1430			IMapDataDestination dest,   object destObject,
1431			int[]               index,
1432			IValueMapper[]      mappers)
1433		{
1434			for (int i = 0; i < index.Length; i++)
1435			{
1436				int n = index[i];
1437
1438				if (n >= 0)
1439					mappers[i].Map(source, sourceObject, i, dest, destObject, n);
1440			}
1441		}
1442
1443		[CLSCompliant(false)]
1444		protected virtual void MapInternal(
1445			InitContext         initContext,
1446			IMapDataSource      source, object sourceObject, 
1447			IMapDataDestination dest,   object destObject,
1448			params object[]     parameters)
1449		{
1450			ISupportMapping smSource = sourceObject as ISupportMapping;
1451			ISupportMapping smDest   = destObject   as ISupportMapping;
1452
1453			if (smSource != null)
1454			{
1455				if (initContext == null)
1456				{
1457					initContext = new InitContext();
1458
1459					initContext.MappingSchema = this;
1460					initContext.DataSource    = source;
1461					initContext.SourceObject  = sourceObject;
1462					initContext.ObjectMapper  = dest as ObjectMapper;
1463					initContext.Parameters    = parameters;
1464				}
1465
1466				initContext.IsSource = true;
1467				smSource.BeginMapping(initContext);
1468				initContext.IsSource = false;
1469
1470				if (initContext.StopMapping)
1471					return;
1472			}
1473
1474			if (smDest != null)
1475			{
1476				if (initContext == null)
1477				{
1478					initContext = new InitContext();
1479
1480					initContext.MappingSchema = this;
1481					initContext.DataSource    = source;
1482					initContext.SourceObject  = sourceObject;
1483					initContext.ObjectMapper  = dest as ObjectMapper;
1484					initContext.Parameters    = parameters;
1485				}
1486
1487				smDest.BeginMapping(initContext);
1488
1489				if (initContext.StopMapping)
1490					return;
1491
1492				if (dest != initContext.ObjectMapper && initContext.ObjectMapper != null)
1493					dest = initContext.ObjectMapper;
1494			}
1495
1496			int[]          index   = GetIndex       (source, dest);
1497			IValueMapper[] mappers = GetValueMappers(source, dest, index);
1498
1499			MapInternal(source, sourceObject, dest, destObject, index, mappers);
1500
1501			if (smDest != null)
1502				smDest.EndMapping(initContext);
1503
1504			if (smSource != null)
1505			{
1506				initContext.IsSource = true;
1507				smSource.EndMapping(initContext);
1508				initContext.IsSource = false;
1509			}
1510		}
1511
1512		protected virtual object MapInternal(InitContext initContext)
1513		{
1514			object dest = initContext.ObjectMapper.CreateInstance(initContext);
1515
1516			if (initContext.StopMapping == false)
1517			{
1518				MapInternal(initContext,
1519					initContext.DataSource, initContext.SourceObject,
1520					initContext.ObjectMapper, dest,
1521					initContext.Parameters);
1522			}
1523
1524			return dest;
1525		}
1526
1527		[CLSCompliant(false)]
1528		public void MapSourceToDestination(
1529			IMapDataSource      source, object sourceObject, 
1530			IMapDataDestination dest,   object destObject,
1531			params object[]     parameters)
1532		{
1533			MapInternal(null, source, sourceObject, dest, destObject, parameters);
1534		}
1535
1536		public void MapSourceToDestination(
1537			object          sourceObject,
1538			object          destObject,
1539			params object[] parameters)
1540		{
1541			IMapDataSource      source = GetDataSource     (sourceObject);
1542			IMapDataDestination dest   = GetDataDestination(destObject);
1543
1544			MapInternal(null, source, sourceObject, dest, destObject, parameters);
1545		}
1546
1547		private static readonly ObjectMapper _nullMapper = new ObjectMapper();
1548
1549		private class MapInfo
1550		{
1551			public int[]          Index;
1552			public IValueMapper[] Mappers;
1553		}
1554
1555		[CLSCompliant(false)]
1556		public virtual void MapSourceListToDestinationList(
1557			IMapDataSourceList      dataSourceList,
1558			IMapDataDestinationList dataDestinationList,
1559			params object[]         parameters)
1560		{
1561			if (dataSourceList      == null) throw new ArgumentNullException("dataSourceList");
1562			if (dataDestinationList == null) throw new ArgumentNullException("dataDestinationList");
1563
1564			Dictionary<ObjectMapper,MapInfo> infos = new Dictionary<ObjectMapper,MapInfo>();
1565
1566			InitContext ctx = new InitContext();
1567
1568			ctx.MappingSchema = this;
1569			ctx.Parameters    = parameters;
1570
1571			dataSourceList.     InitMapping(ctx); if (ctx.StopMapping) return;
1572			dataDestinationList.InitMapping(ctx); if (ctx.StopMapping) return;
1573
1574			int[]               index   = null;
1575			IValueMapper[]      mappers = null;
1576			ObjectMapper        current = _nullMapper;
1577			IMapDataDestination dest    = dataDestinationList.GetDataDestination(ctx);
1578			ObjectMapper        om      = dest as ObjectMapper;
1579
1580			while (dataSourceList.SetNextDataSource(ctx))
1581			{
1582				ctx.ObjectMapper = om;
1583				ctx.StopMapping  = false;
1584
1585				object destObject = dataDestinationList.GetNextObject(ctx);
1586
1587				if (ctx.StopMapping) continue;
1588
1589				ISupportMapping smSource = ctx.SourceObject as ISupportMapping;
1590				ISupportMapping smDest   = destObject       as ISupportMapping;
1591
1592				if (smSource != null)
1593				{
1594					ctx.IsSource = true;
1595					smSource.BeginMapping(ctx);
1596					ctx.IsSource = false;
1597
1598					if (ctx.StopMapping)
1599						continue;
1600				}
1601
1602				if (smDest != null)
1603				{
1604					smDest.BeginMapping(ctx);
1605
1606					if (ctx.StopMapping)
1607						continue;
1608				}
1609
1610				IMapDataDestination currentDest = current ?? dest;
1611
1612				if (current != ctx.ObjectMapper)
1613				{
1614					current     = ctx.ObjectMapper;
1615					currentDest = current ?? dest;
1616
1617					if (current != null)
1618					{
1619						MapInfo info;
1620						if (!infos.TryGetValue(current, out info))
1621						{
1622							info = new MapInfo();
1623
1624							info.Index   = GetIndex(ctx.DataSource, currentDest);
1625							info.Mappers = GetValueMappers(ctx.DataSource, currentDest, info.Index);
1626
1627							infos.Add(current, info);
1628						}
1629
1630						index   = info.Index;
1631						mappers = info.Mappers;
1632					}
1633					else
1634					{
1635						index   = GetIndex(ctx.DataSource, currentDest);
1636						mappers = GetValueMappers(ctx.DataSource, currentDest, index);
1637					}
1638				}
1639
1640				MapInternal(
1641					ctx.DataSource,
1642					ctx.SourceObject,
1643					currentDest,
1644					destObject,
1645					index,
1646					mappers);
1647
1648				if (smDest != null)
1649					smDest.EndMapping(ctx);
1650
1651				if (smSource != null)
1652				{
1653					ctx.IsSource = true;
1654					smSource.EndMapping(ctx);
1655					ctx.IsSource = false;
1656				}
1657			}
1658
1659			dataDestinationList.EndMapping(ctx);
1660			dataSourceList.     EndMapping(ctx);
1661		}
1662
1663		#endregion
1664
1665		#region ValueToEnum, EnumToValue
1666
1667		[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
1668		public virtual object MapValueToEnum(object value, Type type)
1669		{
1670			if (value == null)
1671				return GetNullValue(type);
1672
1673			MapValue[] mapValues = GetMapValues(type);
1674
1675            var mapValueType = GetMapValueType(mapValues);
1676            if (mapValueType != null && value.GetType() != mapValueType)
1677            {
1678                value = ConvertChangeType(value, mapValueType);
1679            }
1680
1681			if (mapValues != null)
1682			{
1683				var comp = (IComparable)value;
1684
1685				foreach (MapValue mv in mapValues)
1686				foreach (object mapValue in mv.MapValues)
1687				{
1688					try
1689					{
1690                        if (comp.CompareTo(mapValue) == 0)
1691                                return mv.OrigValue;
1692                        }
1693					catch (ArgumentException ex)
1694					{
1695						Debug.WriteLine(ex.Message, MethodBase.GetCurrentMethod().Name);
1696					}
1697				}
1698			}
1699
1700			InvalidCastException exInvalidCast = null;
1701
1702			var enumType = TypeHelper.UnwrapNullableType(type);
1703			try
1704			{
1705				value = ConvertChangeType(value, Enum.GetUnderlyingType(enumType));
1706
1707				if (Enum.IsDefined(enumType, value))
1708				{
1709					// Regular (known) enum field w/o explicit mapping defined.
1710					//
1711					return Enum.ToObject(enumType, value);
1712				}
1713			}
1714			catch (InvalidCastException ex)
1715			{
1716				exInvalidCast = ex;
1717			}
1718
1719			// Default value.
1720			//
1721			object defaultValue = GetDefaultValue(type);
1722
1723			if (defaultValue != null)
1724				return defaultValue;
1725
1726			if (exInvalidCast != null)
1727			{
1728				// Rethrow an InvalidCastException when no default value specified.
1729				//
1730				throw exInvalidCast;
1731			}
1732
1733			// At this point we have an undefined enum value.
1734			//
1735			return Enum.ToObject(enumType, value);
1736		}
1737
1738		[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
1739		public virtual object MapValueToEnum(object value, MemberAccessor ma)
1740		{
1741			if (value == null || value is DBNull)
1742				return GetNullValue(ma.Type);
1743
1744			MapValue[] mapValues = GetMapValues(ma);
1745
1746			var mapValueType = GetMapValueType(mapValues);
1747			if (mapValueType != null && value.GetType() != mapValueType)
1748			{
1749				value = ConvertChangeType(value, mapValueType);
1750			}
1751
1752			if (mapValues != null)
1753			{
1754				var comp = (IComparable)value;
1755
1756				foreach (MapValue mv in mapValues)
1757					foreach (object mapValue in mv.MapValues)
1758					{
1759						try
1760						{
1761							if (comp.CompareTo(mapValue) == 0)
1762								return mv.OrigValue;
1763						}
1764						catch (ArgumentException ex)
1765						{
1766							Debug.WriteLine(ex.Message, MethodBase.GetCurrentMethod().Name);
1767						}
1768					}
1769			}
1770
1771			InvalidCastException exInvalidCast = null;
1772
1773			var enumType = TypeHelper.UnwrapNullableType(ma.Type);
1774			try
1775			{
1776				value = ConvertChangeType(value, Enum.GetUnderlyingType(enumType));
1777
1778				if (Enum.IsDefined(enumType, value))
1779				{
1780					// Re…

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