// Copyright 2009-2022 Josh Close // This file is a part of CsvHelper and is dual licensed under MS-PL and Apache 2.0. // See LICENSE.txt for details or visit http://www.opensource.org/licenses/ms-pl.html for MS-PL and http://opensource.org/licenses/Apache-2.0 for Apache 2.0. // https://github.com/JoshClose/CsvHelper using System; using System.Linq.Expressions; using CsvHelper.TypeConversion; using System.Collections; namespace CsvHelper.Configuration { /// /// Has mapping capabilities. /// /// The class type. public interface IHasMap : IBuildableClass { /// /// Maps a member to a CSV field. /// /// The member to map. /// If true, an existing map will be used if available. /// If false, a new map is created for the same member. /// The member mapping. IHasMapOptions Map(Expression> expression, bool useExistingMap = true); } /// /// Options after a mapping call. /// /// The class type. /// The member type. public interface IHasMapOptions : IHasMap, IHasTypeConverter, IHasIndex, IHasName, IHasOptional, IHasConvertUsing, IHasDefault, IHasConstant, IHasValidate { } /// /// Has type converter capabilities. /// /// The class type. /// The member type. public interface IHasTypeConverter : IBuildableClass { /// /// Specifies the to use /// when converting the member to and from a CSV field. /// /// The TypeConverter to use. IHasTypeConverterOptions TypeConverter(ITypeConverter typeConverter); /// /// Specifies the to use /// when converting the member to and from a CSV field. /// /// The of the /// to use. IHasTypeConverterOptions TypeConverter() where TConverter : ITypeConverter; } /// /// Options after a type converter call. /// /// The class type. /// The member type. public interface IHasTypeConverterOptions : IHasMap, IHasDefault, IHasValidate { } /// /// Has index capabilities. /// /// The class type. /// The member type. public interface IHasIndex : IBuildableClass { /// /// When reading, is used to get the field at /// the given index. When writing, the fields /// will be written in the order of the field /// indexes. /// /// The index of the CSV field. /// The end index used when mapping to an member. IHasIndexOptions Index(int index, int indexEnd = -1); } /// /// Options after an index call. /// /// The class type. /// The member type. public interface IHasIndexOptions : IHasMap, IHasTypeConverter, IHasName, IHasDefault, IHasValidate { } /// /// Has optional capabilities. /// /// The class type. /// The member type. public interface IHasOptional : IBuildableClass { /// /// Ignore the member when reading if no matching field name can be found. /// IHasOptionalOptions Optional(); } /// /// Options after an optional call. /// /// The class type. /// The member type. public interface IHasOptionalOptions : IHasMap, IHasTypeConverter, IHasName, IHasDefault, IHasValidate { } /// /// Has name capabilities. /// /// The class type. /// The member type. public interface IHasName : IBuildableClass { /// /// When reading, is used to get the field /// at the index of the name if there was a /// header specified. It will look for the /// first name match in the order listed. /// When writing, sets the name of the /// field in the header record. /// The first name will be used. /// /// The possible names of the CSV field. IHasNameOptions Name(params string[] names); } /// /// Options after a name call. /// /// The class type. /// The member type. public interface IHasNameOptions : IHasMap, IHasTypeConverter, IHasNameIndex, IHasDefault, IHasValidate { } /// /// Has name index capabilities. /// /// The class type. /// The member type. public interface IHasNameIndex : IBuildableClass { /// /// When reading, is used to get the /// index of the name used when there /// are multiple names that are the same. /// /// The index of the name. IHasNameIndexOptions NameIndex(int index); } /// /// Options after a name index call. /// /// The class type. /// The member type. public interface IHasNameIndexOptions : IHasMap, IHasTypeConverter, IHasDefault, IHasValidate { } /// /// Has convert using capabilities. /// /// The class type. /// The member type. public interface IHasConvertUsing : IBuildableClass { /// /// Specifies an expression to be used to convert data in the /// row to the member. /// /// The convert expression. IHasMap ConvertUsing(ConvertFromString convertExpression); /// /// Specifies an expression to be used to convert the object /// to a field. /// /// The convert expression. IHasMap ConvertUsing(ConvertToString convertExpression); } /// /// Has default capabilities. /// /// The class type. /// The member type. public interface IHasDefault : IBuildableClass { /// /// The default value that will be used when reading when /// the CSV field is empty. /// /// The default value. IHasDefaultOptions Default(TMember defaultValue); /// /// The default value that will be used when reading when /// the CSV field is empty. This value is not type checked /// and will use a to convert /// the field. This could potentially have runtime errors. /// /// The default value. IHasDefaultOptions Default(string defaultValue); } /// /// Options after a default call. /// /// The class type. /// The member type. public interface IHasDefaultOptions : IHasMap, IHasValidate { } /// /// Has constant capabilities. /// /// The class type. /// The member type. public interface IHasConstant : IBuildableClass { /// /// The constant value that will be used for every record when /// reading and writing. This value will always be used no matter /// what other mapping configurations are specified. /// /// The constant value. IHasMap Constant(TMember value); } /// /// Has validate capabilities. /// /// The class type. /// The member type. public interface IHasValidate : IBuildableClass { /// /// The validate expression that will be called on every field when reading. /// The expression should return true if the field is valid. /// If false is returned, a /// will be thrown. /// /// The validation expression. IHasMap Validate(Validate validateExpression); } /// /// Has build capabilities. /// /// The class type. public interface IBuildableClass { /// /// Builds the . /// ClassMap Build(); } internal class ClassMapBuilder : IHasMap { private readonly ClassMap map; public ClassMapBuilder() { map = new BuilderClassMap(); } public IHasMapOptions Map(Expression> expression, bool useExistingMap = true) { return new MemberMapBuilder(map, map.Map(expression, useExistingMap)); } public ClassMap Build() { return map; } private class BuilderClassMap : ClassMap { } } internal class MemberMapBuilder : IHasMap, IHasMapOptions, IHasTypeConverter, IHasTypeConverterOptions, IHasIndex, IHasIndexOptions, IHasName, IHasNameOptions, IHasNameIndex, IHasNameIndexOptions, IHasOptional, IHasOptionalOptions, IHasConvertUsing, IHasDefault, IHasDefaultOptions, IHasConstant, IHasValidate { private readonly ClassMap classMap; private readonly MemberMap memberMap; public MemberMapBuilder(ClassMap classMap, MemberMap memberMap) { this.classMap = classMap; this.memberMap = memberMap; } #pragma warning disable CS0693 // Type parameter has the same name as the type parameter from outer type public IHasMapOptions Map(Expression> expression, bool useExistingMap = true) { return new MemberMapBuilder(classMap, classMap.Map(expression, useExistingMap)); } #pragma warning restore CS0693 // Type parameter has the same name as the type parameter from outer type public IHasMap ConvertUsing(ConvertFromString convertExpression) { memberMap.Convert(convertExpression); return this; } public IHasMap ConvertUsing(ConvertToString convertExpression) { memberMap.Convert(convertExpression); return this; } public IHasDefaultOptions Default(TMember defaultValue) { memberMap.Default(defaultValue); return this; } public IHasDefaultOptions Default(string defaultValue) { memberMap.Default(defaultValue); return this; } public IHasIndexOptions Index(int index, int indexEnd = -1) { memberMap.Index(index, indexEnd); return this; } public IHasNameOptions Name(params string[] names) { memberMap.Name(names); return this; } public IHasNameIndexOptions NameIndex(int index) { memberMap.NameIndex(index); return this; } public IHasOptionalOptions Optional() { memberMap.Optional(); return this; } public IHasTypeConverterOptions TypeConverter(ITypeConverter typeConverter) { memberMap.TypeConverter(typeConverter); return this; } public IHasTypeConverterOptions TypeConverter() where TConverter : ITypeConverter { memberMap.TypeConverter(); return this; } public IHasMap Constant(TMember value) { memberMap.Constant(value); return this; } public IHasMap Validate(Validate validateExpression) { memberMap.Validate(validateExpression); return this; } public ClassMap Build() { return classMap; } } }