/// <summary>Finds all the ClassToDataTableAttribute that are decorating the properties.</summary> private bool FindClassToDataTableAttributesOnOneProperty(ClassPropertyToDataTableColumnMap newMap) { ClassToDataTableAttribute ctdtAttribute = newMap.PropInformation.HelpFindAttribute <ClassToDataTableAttribute>(); // Should we add this column? if (ctdtAttribute != null) { if (ctdtAttribute.Ignore) { return(true); } // Is there an override for column name? If not, we assigned the property name above. if (string.IsNullOrWhiteSpace(ctdtAttribute.ColumnName) == false) { newMap.ColumnName = ctdtAttribute.ColumnName; } // Did the user specify a column order? if (ctdtAttribute.Order > 0) { newMap.Order = ctdtAttribute.Order; } } return(false); }
/// <summary>Finds all the ClassToDataTableConverterAttribute that are decorating the properties.</summary> private void FindConvertersOnOneProperty(ClassPropertyToDataTableColumnMap newMap) { var attributeList = newMap.PropInformation.HelpFindAllAttributes <ClassToDataTableConverterAttribute>(); if (attributeList.Count == 1) { AddOneConverterToTheMap(newMap, attributeList[0]); } else if (attributeList.Count > 1) { throw new ArgumentException($"The {newMap.PropInformation.Name} property on the {_theClassType.Name} class " + $"specified more than one {nameof(ClassToDataTableConverterAttribute)} " + $"attribute and is allowed per property on a class. Please remove one of the attributes!"); } }
/// <summary>Creates the property maps</summary> private List <ClassPropertyToDataTableColumnMap> CreateColumnMaps() { var mapList = new List <ClassPropertyToDataTableColumnMap>(); foreach (PropertyInfo info in _theClassType.GetProperties()) { var newMap = new ClassPropertyToDataTableColumnMap { Order = 99999, ColumnIndex = 0, ColumnName = info.Name, // use property name by default PropInformation = info }; bool ignoreColumn = FindClassToDataTableAttributesOnOneProperty(newMap); if (ignoreColumn) { continue; } FindConvertersOnOneProperty(newMap); // If no converter was specified, ignore properties that the DataTable cannot convert! if (newMap.Converter == null && _validDataTableDataTypes.IsValidType(info.PropertyType) == false) { // Has the user chosen to ignore invalid types on the class? If so, just don't create the map; // otherwise, throw the exception that follows. if (_configuration.IgnoreInvalidTypes) { continue; } throw new ArgumentException($"The {newMap.PropInformation.Name} property on the {_theClassType.Name} class " + $"has a type of {info.PropertyType.Name}, which is NOT supported by DataTable. Please ignore the " + $"column using the {nameof(ClassToDataTableAttribute)} attribute's Ignore setting OR set the service " + $"Configuration's IgnoreInvalidTypes property to true. Please refer to this link for more information " + $"about valid DataTable types: https://docs.microsoft.com/en-us/dotnet/api/system.data.datacolumn.datatype?view=net-5.0#remarks"); } mapList.Add(newMap); } FindConvertersOnTheClass(mapList); // Sort the columns the way the user wants them sorted or by column name return(mapList.OrderBy(o => o.Order).ThenBy(o => o.ColumnName).ToList()); }
/// <summary>Adds one converter to the column map.</summary> /// <param name="newMap">The column map</param> /// <param name="oneCustomAttribute">The attribute that specified the type converter. We need to use it to initialize the converter.</param> private void AddOneConverterToTheMap(ClassPropertyToDataTableColumnMap newMap, ClassToDataTableConverterAttribute oneCustomAttribute) { newMap.Converter = oneCustomAttribute.TypeConverter.HelpCreateAndCastToInterface <IClassToDataTableTypeConverter>( $"The '{newMap.PropInformation.Name}' property on the {_theClassType.Name} class specified a converter, but there is a problem!"); newMap.Converter.Initialize(oneCustomAttribute); newMap.OutputType = newMap.Converter.OutputType; if (_validDataTableDataTypes.IsValidType(newMap.OutputType) == false) { throw new ArgumentException($"The {newMap.PropInformation.Name} property on the {_theClassType.Name} class is using a converter " + $"with an output type of {newMap.OutputType.Name}, which is NOT supported by DataTable. Please refer to this link " + "for more information about valid DataTable types: " + "https://docs.microsoft.com/en-us/dotnet/api/system.data.datacolumn.datatype?view=net-5.0#remarks"); } if (newMap.Converter.CanConvert(newMap.PropInformation.PropertyType) == false) { throw new ArgumentException($"The {newMap.PropInformation.Name} property on the {_theClassType.Name} class " + $"has a {nameof(ClassToDataTableConverterAttribute)}, but it cannot convert a data of the " + $"{newMap.PropInformation.PropertyType.Name} type!"); } }