File: System\Data\Common\DataColumnMapping.cs
Web Access
Project: src\src\libraries\System.Data.Common\src\System.Data.Common.csproj (System.Data.Common)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.ComponentModel;
using System.ComponentModel.Design.Serialization;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Reflection;
 
namespace System.Data.Common
{
    [TypeConverter(typeof(DataColumnMappingConverter))]
    public sealed class DataColumnMapping : MarshalByRefObject, IColumnMapping, ICloneable
    {
        private DataColumnMappingCollection? _parent;
        private string? _dataSetColumnName;
        private string? _sourceColumnName;
 
        public DataColumnMapping()
        {
        }
 
        public DataColumnMapping(string? sourceColumn, string? dataSetColumn)
        {
            SourceColumn = sourceColumn;
            DataSetColumn = dataSetColumn;
        }
 
        [DefaultValue("")]
        [AllowNull]
        public string DataSetColumn
        {
            get { return _dataSetColumnName ?? string.Empty; }
            set { _dataSetColumnName = value; }
        }
 
        internal DataColumnMappingCollection? Parent
        {
            get
            {
                return _parent;
            }
            set
            {
                _parent = value;
            }
        }
 
        [DefaultValue("")]
        [AllowNull]
        public string SourceColumn
        {
            get { return _sourceColumnName ?? string.Empty; }
            set
            {
                if ((null != Parent) && (0 != ADP.SrcCompare(_sourceColumnName, value)))
                {
                    Parent.ValidateSourceColumn(-1, value);
                }
                _sourceColumnName = value;
            }
        }
 
        object ICloneable.Clone()
        {
            DataColumnMapping clone = new DataColumnMapping();
            clone._sourceColumnName = _sourceColumnName;
            clone._dataSetColumnName = _dataSetColumnName;
            return clone;
        }
 
        [EditorBrowsable(EditorBrowsableState.Advanced)]
        public DataColumn? GetDataColumnBySchemaAction(DataTable dataTable, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.PublicFields)] Type? dataType, MissingSchemaAction schemaAction)
        {
            return GetDataColumnBySchemaAction(SourceColumn, DataSetColumn, dataTable, dataType, schemaAction);
        }
 
        [EditorBrowsable(EditorBrowsableState.Advanced)]
        public static DataColumn? GetDataColumnBySchemaAction(string? sourceColumn, string? dataSetColumn, DataTable dataTable, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.PublicFields)] Type? dataType, MissingSchemaAction schemaAction)
        {
            if (null == dataTable)
            {
                throw ADP.ArgumentNull(nameof(dataTable));
            }
            if (string.IsNullOrEmpty(dataSetColumn))
            {
                return null;
            }
            DataColumnCollection columns = dataTable.Columns;
            Debug.Assert(null != columns, "GetDataColumnBySchemaAction: unexpected null DataColumnCollection");
 
            int index = columns.IndexOf(dataSetColumn);
            if ((0 <= index) && (index < columns.Count))
            {
                DataColumn dataColumn = columns[index];
                Debug.Assert(null != dataColumn, "GetDataColumnBySchemaAction: unexpected null dataColumn");
 
                if (!string.IsNullOrEmpty(dataColumn.Expression))
                {
                    throw ADP.ColumnSchemaExpression(sourceColumn, dataSetColumn);
                }
 
                if ((null == dataType) || (dataType.IsArray == dataColumn.DataType.IsArray))
                {
                    return dataColumn;
                }
 
                throw ADP.ColumnSchemaMismatch(sourceColumn, dataType, dataColumn);
            }
 
            return CreateDataColumnBySchemaAction(sourceColumn, dataSetColumn, dataTable, dataType, schemaAction);
        }
 
        internal static DataColumn? CreateDataColumnBySchemaAction(string? sourceColumn, string? dataSetColumn, DataTable dataTable, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.PublicFields)] Type? dataType, MissingSchemaAction schemaAction)
        {
            Debug.Assert(dataTable != null, "Should not call with a null DataTable");
            if (string.IsNullOrEmpty(dataSetColumn))
            {
                return null;
            }
 
            switch (schemaAction)
            {
                case MissingSchemaAction.Add:
                case MissingSchemaAction.AddWithKey:
                    return new DataColumn(dataSetColumn, dataType!);
 
                case MissingSchemaAction.Ignore:
                    return null;
 
                case MissingSchemaAction.Error:
                    throw ADP.ColumnSchemaMissing(dataSetColumn, dataTable.TableName, sourceColumn);
            }
            throw ADP.InvalidMissingSchemaAction(schemaAction);
        }
 
        public override string ToString()
        {
            return SourceColumn;
        }
 
        internal sealed class DataColumnMappingConverter : System.ComponentModel.ExpandableObjectConverter
        {
            // converter classes should have public ctor
            public DataColumnMappingConverter()
            {
            }
 
            public override bool CanConvertTo(ITypeDescriptorContext? context, [NotNullWhen(true)] Type? destinationType)
            {
                if (typeof(InstanceDescriptor) == destinationType)
                {
                    return true;
                }
                return base.CanConvertTo(context, destinationType);
            }
 
            public override object? ConvertTo(ITypeDescriptorContext? context, CultureInfo? culture, object? value, Type destinationType)
            {
                if (null == destinationType)
                {
                    throw ADP.ArgumentNull(nameof(destinationType));
                }
 
                if ((typeof(InstanceDescriptor) == destinationType) && (value is DataColumnMapping))
                {
                    DataColumnMapping mapping = (DataColumnMapping)value;
 
                    object[] values = new object[] { mapping.SourceColumn, mapping.DataSetColumn };
                    Type[] types = new Type[] { typeof(string), typeof(string) };
 
                    ConstructorInfo ctor = typeof(DataColumnMapping).GetConstructor(types)!;
                    return new InstanceDescriptor(ctor, values);
                }
                return base.ConvertTo(context, culture, value, destinationType);
            }
        }
    }
}