├── .gitattributes ├── .gitignore ├── ChangeLog.md ├── LICENSE ├── README.md ├── appveyor.yml ├── assets ├── build.bat ├── icon_256.png ├── icon_v1_160.jpg ├── psake-common.ps1 └── psake-project.ps1 ├── nuspecs ├── FlatFile.Core.Attributes.nuspec ├── FlatFile.Core.nuspec ├── FlatFile.Delimited.Attributes.nuspec ├── FlatFile.Delimited.nuspec ├── FlatFile.FixedLength.Attributes.nuspec ├── FlatFile.FixedLength.nuspec └── FlatFile.nuspec └── src ├── .editorconfig ├── .nuget ├── NuGet.Config ├── nuget.exe └── packages.config ├── FlatFile.Benchmark ├── Converters │ ├── CsvHelperTypeConverterForCustomType.cs │ └── FlatFileTypeConverterForCustomType.cs ├── Entities │ ├── CustomObject.cs │ ├── CustomType.cs │ └── FixedSampleRecord.cs ├── FlatFile.Benchmark.csproj ├── FlatFileVsCsvHelperBenchmark.cs ├── FlatFileVsFileHelpersBenchmark.cs ├── Generators │ └── FakeGenarator.cs ├── Mapping │ ├── CsvHelperMappingForCustomObject.cs │ ├── DelimitedSampleRecordLayout.cs │ ├── FixedSampleRecordLayout.cs │ └── FlatFileMappingForCustomObject.cs ├── Properties │ └── AssemblyInfo.cs └── packages.config ├── FlatFile.Core.Attributes ├── Base │ ├── FieldSettingsBaseAttribute.cs │ └── LayoutBaseAttribute.cs ├── Entities │ └── PropertyDescription.cs ├── Extensions │ ├── AttributeUtil.cs │ └── TypeExtensions.cs ├── FlatFile.Core.Attributes.csproj ├── Infrastructure │ └── ILayoutDescriptorProvider.cs └── Properties │ └── AssemblyInfo.cs ├── FlatFile.Core ├── Base │ ├── FieldSettingsBase.cs │ ├── FieldsContainer.cs │ ├── FlatFileEngine.cs │ ├── LayoutBase.cs │ ├── LayoutDescriptorBase.cs │ ├── LineBulderBase.cs │ └── LineParserBase.cs ├── Exceptions │ └── ParseLineException.cs ├── Extensions │ ├── ExpressionExtensions.cs │ ├── FieldsSettingsExtensions.cs │ ├── ReflectionHelper.cs │ ├── TypeChangeExtensions.cs │ └── TypeExtensions.cs ├── FlatFile.Core.csproj ├── IFieldSettingsConstructor.cs ├── IFieldSettingsFactory.cs ├── IFieldsContainer.cs ├── IFlatFileEngine.cs ├── IFlatFileEngineFactory.cs ├── IFlatFileMultiEngine.cs ├── ILayout.cs ├── ILayoutDescriptor.cs ├── ILineBuilderFactory.cs ├── ILineBulder.cs ├── ILineParser.cs ├── ILineParserFactory.cs ├── ITypeConverter.cs └── Properties │ └── AssemblyInfo.cs ├── FlatFile.Delimited.Attributes ├── DelimitedFieldAttribute.cs ├── DelimitedFileAttribute.cs ├── FlatFile.Delimited.Attributes.csproj ├── FlatFileEngineFactoryExtensions.cs ├── Infrastructure │ ├── DelimitedLayoutDescriptorProvider.cs │ └── DelimitedMultiLayoutDescriptor.cs └── Properties │ └── AssemblyInfo.cs ├── FlatFile.Delimited ├── DelimitedFieldSettings.cs ├── FlatFile.Delimited.csproj ├── IDelimitedFieldSettingsConstructor.cs ├── IDelimitedLayout.cs ├── IDelimitedLayoutDescriptor.cs ├── IDelimitedLineBuilder.cs ├── IDelimitedLineBuilderFactory.cs ├── IDelimitedLineParser.cs ├── IDelimitedLineParserFactory.cs ├── IDetailRecord.cs ├── IMasterRecord.cs ├── Implementation │ ├── DelimetedFileMultiEngine.cs │ ├── DelimitedFieldSettingsConstructor.cs │ ├── DelimitedFieldSettingsFactory.cs │ ├── DelimitedFileEngine.cs │ ├── DelimitedFileEngineFactory.cs │ ├── DelimitedLayout.cs │ ├── DelimitedLineBuilder.cs │ ├── DelimitedLineBuilderFactory.cs │ ├── DelimitedLineParser.cs │ └── DelimitedLineParserFactory.cs └── Properties │ └── AssemblyInfo.cs ├── FlatFile.FixedLength.Attributes ├── FixedLengthFieldAttribute.cs ├── FixedLengthFileAttribute.cs ├── FlatFile.FixedLength.Attributes.csproj ├── FlatFileEngineFactoryExtensions.cs ├── Infrastructure │ └── FixedLayoutDescriptorProvider.cs └── Properties │ └── AssemblyInfo.cs ├── FlatFile.FixedLength ├── FixedFieldSettings.cs ├── FlatFile.FixedLength.csproj ├── IDetailRecord.cs ├── IFixedFieldSettingsConstructor.cs ├── IFixedLayout.cs ├── IFixedLengthLineBuilder.cs ├── IFixedLengthLineBuilderFactory.cs ├── IFixedLengthLineParser.cs ├── IFixedLengthLineParserFactory.cs ├── IMasterRecord.cs ├── Implementation │ ├── FixedFieldSettingsConstructor.cs │ ├── FixedFieldSettingsFactory.cs │ ├── FixedLayout.cs │ ├── FixedLengthFileEngine.cs │ ├── FixedLengthFileEngineFactory.cs │ ├── FixedLengthFileMultiEngine.cs │ ├── FixedLengthLineBuilder.cs │ ├── FixedLengthLineBuilderFactory.cs │ ├── FixedLengthLineParser.cs │ └── FixedLengthLineParserFactory.cs ├── Padding.cs └── Properties │ └── AssemblyInfo.cs ├── FlatFile.Tests ├── App.config ├── Base │ ├── Entities │ │ └── TestObject.cs │ └── IntegrationTests.cs ├── Core │ └── FieldsContainerTests.cs ├── Delimited │ ├── DelimitedAttributeMappingIntegrationTests.cs │ ├── DelimitedIntegrationTests.cs │ ├── DelimitedLayoutTests.cs │ ├── DelimitedMultiEngineTests.cs │ └── DelimitedWithHeaderIntegrationTests.cs ├── FixedLength │ ├── FixedLayoutTests.cs │ ├── FixedLengthAttributeMappingIntegrationTests.cs │ ├── FixedLengthIntegrationTests.cs │ ├── FixedLengthLineParserTests.cs │ ├── FixedLengthMasterDetailTests.cs │ └── FixedLengthMultiEngineTests.cs ├── FlatFile.Tests.csproj ├── Properties │ └── AssemblyInfo.cs ├── Specifications │ ├── Defenitions │ │ └── FixedLengthFileDefinitions.cs │ ├── Entities │ │ └── FixedLengthTypeMapping.cs │ ├── Extensions │ │ ├── FileEngineExtensions.cs │ │ ├── ScenarioContextExtensions.cs │ │ └── StringExtensions.cs │ ├── FixedLengthFileMappingFeature.feature │ ├── FixedLengthFileMappingFeature.feature.cs │ └── Transforms │ │ └── TransformsBinding.cs └── packages.config ├── FlatFile.sln └── SharedAssemblyInfo.cs /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.sln.docstates 8 | 9 | # Build results 10 | 11 | [Dd]ebug/ 12 | [Rr]elease/ 13 | x64/ 14 | build/ 15 | [Bb]in/ 16 | [Oo]bj/ 17 | 18 | # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets 19 | !packages/*/build/ 20 | 21 | # MSTest test Results 22 | [Tt]est[Rr]esult*/ 23 | [Bb]uild[Ll]og.* 24 | 25 | *_i.c 26 | *_p.c 27 | *.ilk 28 | *.meta 29 | *.obj 30 | *.pch 31 | *.pdb 32 | *.pgc 33 | *.pgd 34 | *.rsp 35 | *.sbr 36 | *.tlb 37 | *.tli 38 | *.tlh 39 | *.tmp 40 | *.tmp_proj 41 | *.log 42 | *.vspscc 43 | *.vssscc 44 | .builds 45 | *.pidb 46 | *.log 47 | *.scc 48 | 49 | # Visual C++ cache files 50 | ipch/ 51 | *.aps 52 | *.ncb 53 | *.opensdf 54 | *.sdf 55 | *.cachefile 56 | 57 | # Visual Studio profiler 58 | *.psess 59 | *.vsp 60 | *.vspx 61 | 62 | # Guidance Automation Toolkit 63 | *.gpState 64 | 65 | # ReSharper is a .NET coding add-in 66 | _ReSharper*/ 67 | *.[Rr]e[Ss]harper 68 | 69 | # TeamCity is a build add-in 70 | _TeamCity* 71 | 72 | # DotCover is a Code Coverage Tool 73 | *.dotCover 74 | 75 | # NCrunch 76 | *.ncrunch* 77 | .*crunch*.local.xml 78 | 79 | # Installshield output folder 80 | [Ee]xpress/ 81 | 82 | # DocProject is a documentation generator add-in 83 | DocProject/buildhelp/ 84 | DocProject/Help/*.HxT 85 | DocProject/Help/*.HxC 86 | DocProject/Help/*.hhc 87 | DocProject/Help/*.hhk 88 | DocProject/Help/*.hhp 89 | DocProject/Help/Html2 90 | DocProject/Help/html 91 | 92 | # Click-Once directory 93 | publish/ 94 | 95 | # Publish Web Output 96 | *.Publish.xml 97 | 98 | # NuGet Packages Directory 99 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 100 | packages/ 101 | 102 | # Windows Azure Build Output 103 | csx 104 | *.build.csdef 105 | 106 | # Windows Store app package directory 107 | AppPackages/ 108 | 109 | # Others 110 | sql/ 111 | *.Cache 112 | ClientBin/ 113 | [Ss]tyle[Cc]op.* 114 | ~$* 115 | *~ 116 | *.dbmdl 117 | *.[Pp]ublish.xml 118 | *.pfx 119 | *.publishsettings 120 | 121 | # RIA/Silverlight projects 122 | Generated_Code/ 123 | 124 | # Backup & report files from converting an old project file to a newer 125 | # Visual Studio version. Backup files are not needed, because we have git ;-) 126 | _UpgradeReport_Files/ 127 | Backup*/ 128 | UpgradeLog*.XML 129 | UpgradeLog*.htm 130 | 131 | # SQL Server files 132 | App_Data/*.mdf 133 | App_Data/*.ldf 134 | 135 | 136 | #LightSwitch generated files 137 | GeneratedArtifacts/ 138 | _Pvt_Extensions/ 139 | ModelManifest.xml 140 | 141 | # ========================= 142 | # Windows detritus 143 | # ========================= 144 | 145 | # Windows image file caches 146 | Thumbs.db 147 | ehthumbs.db 148 | 149 | # Folder config file 150 | Desktop.ini 151 | 152 | # Recycle Bin used on file shares 153 | $RECYCLE.BIN/ 154 | 155 | # Mac desktop service store files 156 | .DS_Store 157 | assets/FlatFile.Core.Compiled.nuspec 158 | assets/FlatFile.Delimited.Compiled.nuspec 159 | assets/FlatFile.FixedLength.Compiled.nuspec 160 | -------------------------------------------------------------------------------- /ChangeLog.md: -------------------------------------------------------------------------------- 1 | # ChangeLog / ReleaseNotes 2 | 3 | ## Version 0.2.23 4 | 5 | * Fixed csv tag in the nuget packages. 6 | * Refactored psake with adding release notes to nuget. -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Pavel Nosovich 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | - 2 | version: 0.2.{build} 3 | 4 | environment: 5 | BuildEnvironment: appveyor 6 | 7 | branches: 8 | only: 9 | - master 10 | 11 | assembly_info: 12 | patch: true 13 | file: AssemblyInfo.* 14 | assembly_version: "{version}" 15 | assembly_file_version: "{version}" 16 | assembly_informational_version: "{version}" 17 | 18 | test: off 19 | 20 | artifacts: 21 | - path: 'build\**\*.nupkg' 22 | 23 | build_script: assets\build.bat pack 24 | 25 | cache: 26 | - src\packages # preserve "packages" directory in the root of build folder 27 | 28 | deploy: 29 | provider: NuGet 30 | api_key: 31 | secure: yNaPU9GGsdDdMjOB5tbQTuIIq4DFHNGUkZP1ZTDDCKQG3g7pZjxcBFZblTMeIawA 32 | artifact: /.*build.*\.nupkg/ 33 | on: 34 | branch: master 35 | 36 | - 37 | version: 0.2.{build} 38 | 39 | environment: 40 | BuildEnvironment: appveyor 41 | 42 | branches: 43 | only: 44 | - /dev.*/ 45 | - /feature.*/ 46 | 47 | assembly_info: 48 | patch: true 49 | file: AssemblyInfo.* 50 | assembly_version: "{version}" 51 | assembly_file_version: "{version}" 52 | assembly_informational_version: "{version}" 53 | 54 | build_script: assets\build.bat pack 55 | 56 | cache: 57 | - src\packages # preserve "packages" directory in the root of build folder 58 | -------------------------------------------------------------------------------- /assets/build.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | src\.nuget\NuGet.exe install src\.nuget\packages.config -OutputDirectory src\packages 4 | 5 | powershell.exe -NoProfile -ExecutionPolicy unrestricted -Command "& {Import-Module '.\src\packages\psake.4.4.1\tools\psake.psm1'; invoke-psake '.\assets\psake-project.ps1' %*; if ($LastExitCode -and $LastExitCode -ne 0) {write-host "ERROR CODE: $LastExitCode" -fore RED; exit $lastexitcode} }" 6 | -------------------------------------------------------------------------------- /assets/icon_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/forcewake/FlatFile/20004b34148fbf5c949ee1c77502a57ad6818e14/assets/icon_256.png -------------------------------------------------------------------------------- /assets/icon_v1_160.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/forcewake/FlatFile/20004b34148fbf5c949ee1c77502a57ad6818e14/assets/icon_v1_160.jpg -------------------------------------------------------------------------------- /assets/psake-common.ps1: -------------------------------------------------------------------------------- 1 | Properties { 2 | ### Directories 3 | $base_dir = $root 4 | $build_dir = "$base_dir\build" 5 | $src_dir = "$base_dir\src" 6 | $package_dir = "$src_dir\packages" 7 | $nuspec_dir = "$base_dir\nuspecs" 8 | $temp_dir = "$build_dir\Temp" 9 | $framework_dir = $env:windir + "\Microsoft.Net\Framework\v4.0.30319" 10 | 11 | ### Tools 12 | $nuget = "$src_dir\.nuget\nuget.exe" 13 | $xunit = "$package_dir\xunit.runners*\tools\xunit.console.clr4.exe" 14 | $7zip = "$package_dir\7-Zip.CommandLine.*\tools\7za.exe" 15 | 16 | ### AppVeyor-related 17 | $appVeyorConfig = "$base_dir\appveyor.yml" 18 | $appVeyor = $env:APPVEYOR 19 | 20 | ### Project information 21 | $solution_path = "$src_dir\$solution" 22 | $sharedAssemblyInfo = "$src_dir\SharedAssemblyInfo.cs" 23 | $config = "Release" 24 | $frameworks = @("NET35", "NET40", "NET45") 25 | 26 | ### Files 27 | $releaseNotes = "$base_dir\ChangeLog.md" 28 | } 29 | 30 | ## Tasks 31 | 32 | Task Restore -Description "Restore NuGet packages for solution." { 33 | "Restoring NuGet packages for '$solution_path'..." 34 | Exec { .$nuget restore $solution_path } 35 | } 36 | 37 | Task Clean -Description "Clean up build and project folders." { 38 | Clean-Directory $build_dir 39 | 40 | if ($solution) { 41 | "Cleaning up '$solution'..." 42 | 43 | foreach ($framework in $frameworks) { 44 | Exec { msbuild $solution_path /target:Clean /nologo /verbosity:minimal /p:Framework=$framework} 45 | } 46 | } 47 | } 48 | 49 | Task Compile -Depends Clean, Restore -Description "Compile all the projects in a solution." { 50 | "Compiling '$solution'..." 51 | 52 | $extra = $null 53 | if ($appVeyor) { 54 | $extra = "/logger:C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" 55 | } 56 | 57 | foreach ($framework in $frameworks) { 58 | Exec { msbuild $solution_path /p:"Configuration=$config;Framework=$framework" /nologo /verbosity:minimal $extra } 59 | } 60 | } 61 | 62 | ### Pack functions 63 | 64 | function Create-Package($project, $version, $notes) { 65 | Create-Directory $temp_dir 66 | Copy-Files "$nuspec_dir\$project.nuspec" $temp_dir 67 | 68 | Try { 69 | Replace-Content "$nuspec_dir\$project.nuspec" '#releaseNotes#' $notes 70 | 71 | Replace-Content "$nuspec_dir\$project.nuspec" '$version$' $version 72 | 73 | Exec { .$nuget pack "$nuspec_dir\$project.nuspec" -OutputDirectory "$build_dir" -BasePath "$build_dir" -Version $version} 74 | } 75 | Finally { 76 | Move-Files "$temp_dir\$project.nuspec" $nuspec_dir 77 | } 78 | } 79 | 80 | function Get-ReleaseNotes { 81 | $content = (Get-Content "$releaseNotes") -Join "`n" 82 | return $content 83 | } 84 | 85 | ### Version functions 86 | 87 | function Get-BuildVersion { 88 | $version = Get-SharedVersion 89 | $buildVersion = $env:APPVEYOR_BUILD_VERSION 90 | 91 | if ($buildVersion -ne $null) { 92 | $version = $buildVersion 93 | } 94 | 95 | return $version 96 | } 97 | 98 | function Get-SharedVersion { 99 | $line = Get-Content "$sharedAssemblyInfo" | where {$_.Contains("AssemblyVersion")} 100 | $line.Split('"')[1] 101 | } 102 | 103 | function Update-AppveyorVersion($version) { 104 | Check-Version($version) 105 | 106 | $versionPattern = "version: [0-9]+(\.([0-9]+|\*)){1,3}" 107 | $versionReplace = "version: $version" 108 | 109 | if (Test-Path $appVeyorConfig) { 110 | "Patching $appVeyorConfig..." 111 | Replace-Content "$appVeyorConfig" $versionPattern $versionReplace 112 | } 113 | } 114 | 115 | 116 | ### Common functions 117 | 118 | function Create-Directory($dir) { 119 | New-Item -Path $dir -Type Directory -Force > $null 120 | } 121 | 122 | function Clean-Directory($dir) { 123 | If (Test-Path $dir) { 124 | "Cleaning up '$dir'..." 125 | Remove-Item "$dir\*" -Recurse -Force 126 | } 127 | } 128 | 129 | function Copy-Files($source, $destination) { 130 | Copy-Item "$source" $destination -Force > $null 131 | } 132 | 133 | function Move-Files($source, $destination) { 134 | Move-Item "$source" $destination -Force > $null 135 | } 136 | 137 | function Replace-Content($file, $pattern, $substring) { 138 | (gc $file) -Replace $pattern, $substring | sc $file 139 | } 140 | -------------------------------------------------------------------------------- /assets/psake-project.ps1: -------------------------------------------------------------------------------- 1 | Properties { 2 | $solution = "FlatFile.sln" 3 | } 4 | 5 | $root = (split-path -parent $MyInvocation.MyCommand.Definition) + '\..' 6 | 7 | Include "$root\assets\psake-common.ps1" 8 | 9 | Task Default -Depends Pack 10 | 11 | Task Pack -Depends Compile -Description "Create NuGet packages and archive files." { 12 | $version = Get-BuildVersion 13 | $releaseNotes = Get-ReleaseNotes 14 | 15 | $projects = @( 16 | "FlatFile.Core", 17 | "FlatFile.Core.Attributes", 18 | "FlatFile.Delimited", 19 | "FlatFile.FixedLength", 20 | "FlatFile.Delimited.Attributes", 21 | "FlatFile.FixedLength.Attributes", 22 | "FlatFile" 23 | ) 24 | 25 | $projects | ForEach { 26 | Create-Package $_ $version $releaseNotes 27 | } 28 | } -------------------------------------------------------------------------------- /nuspecs/FlatFile.Core.Attributes.nuspec: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/forcewake/FlatFile/20004b34148fbf5c949ee1c77502a57ad6818e14/nuspecs/FlatFile.Core.Attributes.nuspec -------------------------------------------------------------------------------- /nuspecs/FlatFile.Core.nuspec: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/forcewake/FlatFile/20004b34148fbf5c949ee1c77502a57ad6818e14/nuspecs/FlatFile.Core.nuspec -------------------------------------------------------------------------------- /nuspecs/FlatFile.Delimited.Attributes.nuspec: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/forcewake/FlatFile/20004b34148fbf5c949ee1c77502a57ad6818e14/nuspecs/FlatFile.Delimited.Attributes.nuspec -------------------------------------------------------------------------------- /nuspecs/FlatFile.Delimited.nuspec: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/forcewake/FlatFile/20004b34148fbf5c949ee1c77502a57ad6818e14/nuspecs/FlatFile.Delimited.nuspec -------------------------------------------------------------------------------- /nuspecs/FlatFile.FixedLength.Attributes.nuspec: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/forcewake/FlatFile/20004b34148fbf5c949ee1c77502a57ad6818e14/nuspecs/FlatFile.FixedLength.Attributes.nuspec -------------------------------------------------------------------------------- /nuspecs/FlatFile.FixedLength.nuspec: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/forcewake/FlatFile/20004b34148fbf5c949ee1c77502a57ad6818e14/nuspecs/FlatFile.FixedLength.nuspec -------------------------------------------------------------------------------- /nuspecs/FlatFile.nuspec: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/forcewake/FlatFile/20004b34148fbf5c949ee1c77502a57ad6818e14/nuspecs/FlatFile.nuspec -------------------------------------------------------------------------------- /src/.editorconfig: -------------------------------------------------------------------------------- 1 | root=true 2 | 3 | [*] 4 | end_of_line = LF 5 | 6 | [*.cs] 7 | indent_style = space 8 | indent_size = 4 9 | 10 | [*.markdown] 11 | indent_style = space 12 | indent_size = 2 13 | 14 | [*.json] 15 | indent_style = space 16 | indent_size = 4 -------------------------------------------------------------------------------- /src/.nuget/NuGet.Config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/.nuget/nuget.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/forcewake/FlatFile/20004b34148fbf5c949ee1c77502a57ad6818e14/src/.nuget/nuget.exe -------------------------------------------------------------------------------- /src/.nuget/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/FlatFile.Benchmark/Converters/CsvHelperTypeConverterForCustomType.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Benchmark.Converters 2 | { 3 | using System; 4 | using CsvHelperTypeConversion = CsvHelper.TypeConversion; 5 | 6 | public class CsvHelperTypeConverterForCustomType : CsvHelperTypeConversion.ITypeConverter 7 | { 8 | private readonly FlatFileTypeConverterForCustomType converter; 9 | 10 | public CsvHelperTypeConverterForCustomType() 11 | { 12 | converter = new FlatFileTypeConverterForCustomType(); 13 | } 14 | 15 | public string ConvertToString(CsvHelperTypeConversion.TypeConverterOptions options, object value) 16 | { 17 | return converter.ConvertToString(value); 18 | } 19 | 20 | public object ConvertFromString(CsvHelperTypeConversion.TypeConverterOptions options, string text) 21 | { 22 | return converter.ConvertFromString(text); 23 | } 24 | 25 | public bool CanConvertFrom(Type type) 26 | { 27 | return converter.CanConvertFrom(type); 28 | } 29 | 30 | public bool CanConvertTo(Type type) 31 | { 32 | return converter.CanConvertTo(type); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/FlatFile.Benchmark/Converters/FlatFileTypeConverterForCustomType.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Benchmark.Converters 2 | { 3 | using System; 4 | using FlatFile.Benchmark.Entities; 5 | using FlatFile.Core; 6 | 7 | public class FlatFileTypeConverterForCustomType : ITypeConverter 8 | { 9 | public bool CanConvertFrom(Type type) 10 | { 11 | return type == typeof(string); 12 | } 13 | 14 | public bool CanConvertTo(Type type) 15 | { 16 | return type == typeof (CustomType); 17 | } 18 | 19 | public string ConvertToString(object source) 20 | { 21 | var obj = (CustomType)source; 22 | return string.Format("{0}|{1}|{2}", obj.First, obj.Second, obj.Third); 23 | } 24 | 25 | public object ConvertFromString(string source) 26 | { 27 | var values = source.Split('|'); 28 | 29 | var obj = new CustomType 30 | { 31 | First = int.Parse(values[0]), 32 | Second = int.Parse(values[1]), 33 | Third = int.Parse(values[2]), 34 | }; 35 | return obj; 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /src/FlatFile.Benchmark/Entities/CustomObject.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Benchmark.Entities 2 | { 3 | using System; 4 | using Newtonsoft.Json; 5 | 6 | public class CustomObject 7 | { 8 | public Guid GuidColumn { get; set; } 9 | 10 | public int IntColumn { get; set; } 11 | 12 | public string StringColumn { get; set; } 13 | 14 | public string IgnoredColumn { get; set; } 15 | 16 | public CustomType CustomTypeColumn { get; set; } 17 | 18 | public override string ToString() 19 | { 20 | return JsonConvert.SerializeObject(this); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /src/FlatFile.Benchmark/Entities/CustomType.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Benchmark.Entities 2 | { 3 | using Newtonsoft.Json; 4 | 5 | public class CustomType 6 | { 7 | public int First { get; set; } 8 | public int Second { get; set; } 9 | public int Third { get; set; } 10 | 11 | public override string ToString() 12 | { 13 | return JsonConvert.SerializeObject(this); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/FlatFile.Benchmark/Entities/FixedSampleRecord.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Benchmark.Entities 2 | { 3 | using System; 4 | using FileHelpers; 5 | 6 | /// 7 | /// Sample fixed length record for testing 8 | /// 9 | [FixedLengthRecord()] 10 | public class FixedSampleRecord : IEquatable 11 | { 12 | [FieldFixedLength(11)] 13 | private long _cuit; 14 | 15 | [FieldFixedLength(160)] 16 | [FieldTrim(TrimMode.Both)] 17 | private string _nombre; 18 | 19 | [FieldFixedLength(6)] 20 | private int _actividad; 21 | 22 | public long Cuit 23 | { 24 | get { return _cuit; } 25 | set { _cuit = value; } 26 | } 27 | 28 | public string Nombre 29 | { 30 | get { return _nombre; } 31 | set { _nombre = value; } 32 | } 33 | 34 | public int Actividad 35 | { 36 | get { return _actividad; } 37 | set { _actividad = value; } 38 | } 39 | 40 | public bool Equals(FixedSampleRecord other) 41 | { 42 | if (ReferenceEquals(null, other)) return false; 43 | if (ReferenceEquals(this, other)) return true; 44 | return _cuit == other._cuit && string.Equals(_nombre, other._nombre) && _actividad == other._actividad; 45 | } 46 | 47 | public override bool Equals(object obj) 48 | { 49 | if (ReferenceEquals(null, obj)) return false; 50 | if (ReferenceEquals(this, obj)) return true; 51 | if (obj.GetType() != this.GetType()) return false; 52 | return Equals((FixedSampleRecord) obj); 53 | } 54 | 55 | public override int GetHashCode() 56 | { 57 | unchecked 58 | { 59 | int hashCode = _cuit.GetHashCode(); 60 | hashCode = (hashCode*397) ^ (_nombre != null ? _nombre.GetHashCode() : 0); 61 | hashCode = (hashCode*397) ^ _actividad; 62 | return hashCode; 63 | } 64 | } 65 | 66 | public static bool operator ==(FixedSampleRecord left, FixedSampleRecord right) 67 | { 68 | return Equals(left, right); 69 | } 70 | 71 | public static bool operator !=(FixedSampleRecord left, FixedSampleRecord right) 72 | { 73 | return !Equals(left, right); 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/FlatFile.Benchmark/FlatFileVsCsvHelperBenchmark.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Benchmark 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Text; 8 | using BenchmarkIt; 9 | using CsvHelper; 10 | using FlatFile.Benchmark.Entities; 11 | using FlatFile.Benchmark.Mapping; 12 | using FlatFile.Delimited.Implementation; 13 | using FluentAssertions; 14 | using Xunit; 15 | 16 | public class FlatFileVsCsvHelperBenchmark 17 | { 18 | [Fact(Skip = "Too long for CI")] 19 | public void WriteAllRecordsWithMapping() 20 | { 21 | var records = new List 22 | { 23 | new CustomObject 24 | { 25 | GuidColumn = new Guid("f96a1c66-4777-4642-86fa-703098065f5f"), 26 | IntColumn = 1, 27 | StringColumn = "one", 28 | CustomTypeColumn = new CustomType 29 | { 30 | First = 1, 31 | Second = 2, 32 | Third = 3, 33 | }, 34 | }, 35 | new CustomObject 36 | { 37 | GuidColumn = new Guid("06776ed9-d33f-470f-bd3f-8db842356330"), 38 | IntColumn = 2, 39 | StringColumn = "two", 40 | CustomTypeColumn = new CustomType 41 | { 42 | First = 4, 43 | Second = 5, 44 | Third = 6, 45 | }, 46 | }, 47 | }; 48 | 49 | Benchmark.This("CsvWriter.WriteRecords", () => 50 | { 51 | using (var memoryStream = new MemoryStream()) 52 | using (var streamWriter = new StreamWriter(memoryStream)) 53 | using (var writer = new CsvWriter(streamWriter)) 54 | { 55 | writer.Configuration.RegisterClassMap(); 56 | 57 | writer.WriteRecords(records); 58 | 59 | streamWriter.Flush(); 60 | } 61 | }) 62 | .Against.This("FlatFileEngine.Write", () => 63 | { 64 | var layout = new FlatFileMappingForCustomObject(); 65 | using (var stream = new MemoryStream()) 66 | { 67 | var factory = new DelimitedFileEngineFactory(); 68 | 69 | var flatFile = factory.GetEngine(layout); 70 | 71 | flatFile.Write(stream, records); 72 | } 73 | }) 74 | .WithWarmup(1000) 75 | .For(10000) 76 | .Iterations() 77 | .PrintComparison(); 78 | } 79 | 80 | [Fact(Skip = "Too long for CI")] 81 | public void ReadAllRecordsWithMapping() 82 | { 83 | const string fileContent = 84 | @"String Column,Int Column,Guid Column,Custom Type Column 85 | one,1,f96a1c66-4777-4642-86fa-703098065f5f,1|2|3 86 | two,2,06776ed9-d33f-470f-bd3f-8db842356330,4|5|6 87 | "; 88 | Benchmark.This("CsvWriter.WriteRecords", () => 89 | { 90 | using (var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(fileContent))) 91 | using (var streamReader = new StreamReader(memoryStream)) 92 | using (var reader = new CsvReader(streamReader)) 93 | { 94 | reader.Configuration.RegisterClassMap(); 95 | 96 | var objects = reader.GetRecords().ToArray(); 97 | } 98 | }) 99 | .Against.This("FlatFileEngine.Write", () => 100 | { 101 | var layout = new FlatFileMappingForCustomObject(); 102 | using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(fileContent))) 103 | { 104 | var factory = new DelimitedFileEngineFactory(); 105 | 106 | var flatFile = factory.GetEngine(layout); 107 | 108 | var objects = flatFile.Read(stream).ToArray(); 109 | 110 | } 111 | }) 112 | .WithWarmup(1000) 113 | .For(10000) 114 | .Iterations() 115 | .PrintComparison(); 116 | } 117 | } 118 | } -------------------------------------------------------------------------------- /src/FlatFile.Benchmark/Generators/FakeGenarator.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Benchmark.Generators 2 | { 3 | using FakeO; 4 | using FlatFile.Benchmark.Entities; 5 | 6 | public class FakeGenarator 7 | { 8 | public FixedSampleRecord Generate(int next) 9 | { 10 | var record = Create.Fake( 11 | c => c.Cuit = next, 12 | c => c.Nombre = String.Random(160), 13 | c => c.Actividad = Number.Next(100, 200)); 14 | 15 | return record; 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /src/FlatFile.Benchmark/Mapping/CsvHelperMappingForCustomObject.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Benchmark.Mapping 2 | { 3 | using CsvHelper.Configuration; 4 | using FlatFile.Benchmark.Converters; 5 | using FlatFile.Benchmark.Entities; 6 | 7 | public sealed class CsvHelperMappingForCustomObject : CsvClassMap 8 | { 9 | public CsvHelperMappingForCustomObject() 10 | { 11 | Map(m => m.CustomTypeColumn).Name("Custom Type Column").Index(3).TypeConverter(); 12 | Map(m => m.GuidColumn).Name("Guid Column").Index(2); 13 | Map(m => m.IntColumn).Name("Int Column").Index(1); 14 | Map(m => m.StringColumn).Name("String Column").Index(0); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /src/FlatFile.Benchmark/Mapping/DelimitedSampleRecordLayout.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Benchmark.Mapping 2 | { 3 | using FlatFile.Benchmark.Entities; 4 | using FlatFile.Delimited.Implementation; 5 | 6 | public sealed class DelimitedSampleRecordLayout : DelimitedLayout 7 | { 8 | public DelimitedSampleRecordLayout() 9 | { 10 | this.WithDelimiter(";") 11 | .WithQuote("\"") 12 | .WithMember(x => x.Cuit) 13 | .WithMember(x => x.Nombre) 14 | .WithMember(x => x.Actividad, c => c.WithName("AnotherName")); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /src/FlatFile.Benchmark/Mapping/FixedSampleRecordLayout.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Benchmark.Mapping 2 | { 3 | using FlatFile.Benchmark.Entities; 4 | using FlatFile.FixedLength.Implementation; 5 | 6 | public sealed class FixedSampleRecordLayout : FixedLayout 7 | { 8 | public FixedSampleRecordLayout() 9 | { 10 | this.WithMember(x => x.Cuit, c => c.WithLength(11)) 11 | .WithMember(x => x.Nombre, c => c.WithLength(160)) 12 | .WithMember(x => x.Actividad, c => c.WithLength(6)); 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /src/FlatFile.Benchmark/Mapping/FlatFileMappingForCustomObject.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Benchmark.Mapping 2 | { 3 | using FlatFile.Benchmark.Converters; 4 | using FlatFile.Benchmark.Entities; 5 | using FlatFile.Delimited.Implementation; 6 | 7 | public sealed class FlatFileMappingForCustomObject : DelimitedLayout 8 | { 9 | public FlatFileMappingForCustomObject() 10 | { 11 | this.WithHeader() 12 | .WithDelimiter(",") 13 | .WithMember(m => m.StringColumn, c => c.WithName("String Column")) 14 | .WithMember(m => m.IntColumn, c => c.WithName("Int Column")) 15 | .WithMember(m => m.GuidColumn, c => c.WithName("Guid Column")) 16 | .WithMember(m => m.CustomTypeColumn, c => c.WithName("Custom Type Column").WithTypeConverter()); 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /src/FlatFile.Benchmark/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("FlatFile.Benchmark")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("EPAM Systems")] 12 | [assembly: AssemblyProduct("FlatFile.Benchmark")] 13 | [assembly: AssemblyCopyright("Copyright © EPAM Systems 2014")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("26c53229-856a-4060-90bc-151ffd28e789")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/FlatFile.Benchmark/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/FlatFile.Core.Attributes/Base/FieldSettingsBaseAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Core.Attributes.Base 2 | { 3 | using System; 4 | using FlatFile.Core.Base; 5 | using FlatFile.Core.Extensions; 6 | 7 | [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)] 8 | public abstract class FieldSettingsBaseAttribute : Attribute, IFieldSettings 9 | { 10 | public int? Index { get; set; } 11 | 12 | public bool IsNullable 13 | { 14 | get { return !string.IsNullOrEmpty(NullValue); } 15 | } 16 | 17 | public string NullValue { get; set; } 18 | 19 | public Type Converter { get; set; } 20 | 21 | public ITypeConverter TypeConverter 22 | { 23 | get { return (ITypeConverter) ReflectionHelper.CreateInstance(Converter, true); } 24 | } 25 | 26 | protected FieldSettingsBaseAttribute(int index) 27 | { 28 | Index = index; 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /src/FlatFile.Core.Attributes/Base/LayoutBaseAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Core.Attributes.Base 2 | { 3 | using System; 4 | 5 | [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] 6 | public abstract class LayoutBaseAttribute : Attribute 7 | { 8 | public bool HasHeader { get; set; } 9 | } 10 | } -------------------------------------------------------------------------------- /src/FlatFile.Core.Attributes/Entities/PropertyDescription.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Core.Attributes.Entities 2 | { 3 | using System; 4 | using System.Reflection; 5 | 6 | internal class PropertyDescription 7 | { 8 | public PropertyInfo Property { get; set; } 9 | public Attribute[] Attributes { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/FlatFile.Core.Attributes/Extensions/AttributeUtil.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | 6 | namespace FlatFile.Core.Attributes.Extensions 7 | { 8 | internal static class AttributeUtil 9 | { 10 | public static T GetAttribute(this FieldInfo field, bool inherited = true) where T : Attribute 11 | { 12 | return field.GetAttributes(inherited).FirstOrDefault(); 13 | } 14 | 15 | 16 | public static T GetAttribute(this MemberInfo member, bool inherited = true) where T : Attribute 17 | { 18 | return member.GetAttributes(inherited).FirstOrDefault(); 19 | } 20 | 21 | 22 | public static T GetAttribute(this PropertyInfo property, bool inherited = true) where T : Attribute 23 | { 24 | return property.GetAttributes(inherited).FirstOrDefault(); 25 | } 26 | 27 | 28 | public static T GetAttribute(this MethodInfo method, bool inherited = true) where T : Attribute 29 | { 30 | return method.GetAttributes(inherited).FirstOrDefault(); 31 | } 32 | 33 | 34 | public static T GetAttribute(this ParameterInfo param, bool inherited = true) where T : Attribute 35 | { 36 | return param.GetAttributes(inherited).FirstOrDefault(); 37 | } 38 | 39 | 40 | public static T GetAttribute(this Type type, bool inherited = true) where T : Attribute 41 | { 42 | return type.GetAttributes(inherited).FirstOrDefault(); 43 | } 44 | 45 | 46 | public static IEnumerable GetAttributes(this MemberInfo member, bool inherited = true) where T : Attribute 47 | { 48 | return (T[]) member.GetCustomAttributes(typeof (T), inherited); 49 | } 50 | 51 | 52 | public static IEnumerable GetAttributes(this PropertyInfo property, bool inherited = true) 53 | where T : Attribute 54 | { 55 | return (T[]) property.GetCustomAttributes(typeof (T), inherited); 56 | } 57 | 58 | 59 | public static IEnumerable GetAttributes(this FieldInfo field, bool inherited = true) where T : Attribute 60 | { 61 | return field.GetCustomAttributes(typeof (T), inherited).Cast(); 62 | } 63 | 64 | 65 | public static IEnumerable GetAttributes(this MethodInfo method, bool inherited = true) where T : Attribute 66 | { 67 | return method.GetCustomAttributes(typeof (T), inherited).Cast(); 68 | } 69 | 70 | 71 | public static IEnumerable GetAttributes(this ParameterInfo param, bool inherited = true) 72 | where T : Attribute 73 | { 74 | return param.GetCustomAttributes(typeof (T), inherited).Cast(); 75 | } 76 | 77 | 78 | public static IEnumerable GetAttributes(this Type type, bool inherited = true) where T : Attribute 79 | { 80 | return type.GetCustomAttributes(typeof (T), inherited).Cast(); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/FlatFile.Core.Attributes/Extensions/TypeExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Core.Attributes.Extensions 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using FlatFile.Core.Attributes.Entities; 7 | 8 | internal static class TypeExtensions 9 | { 10 | public static IEnumerable GetTypeDescription(this Type targetType) where TAttribute : Attribute 11 | { 12 | var properties = from p in targetType.GetProperties() 13 | where Attribute.IsDefined(p, typeof(TAttribute)) 14 | let attr = p.GetCustomAttributes(typeof(TAttribute), true) 15 | select new PropertyDescription { Property = p, Attributes = attr.Cast().ToArray() }; 16 | 17 | return properties; 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /src/FlatFile.Core.Attributes/FlatFile.Core.Attributes.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {5849B415-6CC1-4615-A94F-265F5BD6F234} 8 | Library 9 | Properties 10 | FlatFile.Core.Attributes 11 | FlatFile.Core.Attributes 12 | v3.5 13 | 512 14 | 15 | NET35 16 | ..\ 17 | true 18 | 19 | 20 | true 21 | full 22 | false 23 | bin\$(Configuration)\$(Framework)\ 24 | DEBUG;TRACE 25 | prompt 26 | 4 27 | 28 | 29 | pdbonly 30 | true 31 | bin\$(Configuration)\$(Framework)\ 32 | TRACE 33 | prompt 34 | 4 35 | bin\$(Configuration)\$(Framework)\$(AssemblyName).XML 36 | 37 | 38 | 39 | 40 | v4.0 41 | AnyCPU 42 | true 43 | full 44 | false 45 | bin\$(Configuration)\$(Framework)\ 46 | DEBUG;TRACE 47 | prompt 48 | 4 49 | 50 | 51 | 52 | 53 | v4.0 54 | AnyCPU 55 | pdbonly 56 | true 57 | bin\$(Configuration)\$(Framework)\ 58 | TRACE 59 | prompt 60 | 4 61 | bin\$(Configuration)\$(Framework)\$(AssemblyName).XML 62 | 63 | 64 | 65 | 66 | v4.5 67 | AnyCPU 68 | true 69 | full 70 | false 71 | bin\$(Configuration)\$(Framework)\ 72 | DEBUG;TRACE 73 | prompt 74 | 4 75 | 76 | 77 | 78 | 79 | v4.5 80 | AnyCPU 81 | pdbonly 82 | true 83 | bin\$(Configuration)\$(Framework)\ 84 | TRACE 85 | prompt 86 | 4 87 | bin\$(Configuration)\$(Framework)\$(AssemblyName).XML 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | {1cb90052-b97a-4ad4-b9fd-20a22914d129} 109 | FlatFile.Core 110 | 111 | 112 | 113 | 120 | -------------------------------------------------------------------------------- /src/FlatFile.Core.Attributes/Infrastructure/ILayoutDescriptorProvider.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Core.Attributes.Infrastructure 2 | { 3 | using FlatFile.Core.Base; 4 | 5 | public interface ILayoutDescriptorProvider 6 | where TFieldSettings : IFieldSettings 7 | where TLayoutDescriptor : ILayoutDescriptor 8 | { 9 | TLayoutDescriptor GetDescriptor(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/FlatFile.Core.Attributes/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("FlatFile.Core.Attributes")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("FlatFile.Core.Attributes")] 13 | [assembly: AssemblyCopyright("Copyright © 2014")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("3825eaff-28bf-4e11-bce8-5fcb63273c03")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | [assembly: InternalsVisibleTo("FlatFile.Tests")] 38 | [assembly: InternalsVisibleTo("FlatFile.Delimited.Attributes")] 39 | [assembly: InternalsVisibleTo("FlatFile.FixedLength.Attributes")] 40 | -------------------------------------------------------------------------------- /src/FlatFile.Core/Base/FieldSettingsBase.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Core.Base 2 | { 3 | using System.Reflection; 4 | 5 | public interface IFieldSettings 6 | { 7 | int? Index { get; set; } 8 | bool IsNullable { get; } 9 | string NullValue { get; } 10 | ITypeConverter TypeConverter { get; } 11 | } 12 | 13 | public interface IFieldSettingsContainer : IFieldSettings 14 | { 15 | PropertyInfo PropertyInfo { get; } 16 | } 17 | 18 | public abstract class FieldSettingsBase : IFieldSettingsContainer 19 | { 20 | protected FieldSettingsBase(PropertyInfo propertyInfo) 21 | { 22 | PropertyInfo = propertyInfo; 23 | } 24 | 25 | protected FieldSettingsBase(IFieldSettings settings) 26 | { 27 | Index = settings.Index; 28 | IsNullable = settings.IsNullable; 29 | NullValue = settings.NullValue; 30 | } 31 | 32 | protected FieldSettingsBase(PropertyInfo propertyInfo, IFieldSettings settings) : this(settings) 33 | { 34 | PropertyInfo = propertyInfo; 35 | } 36 | 37 | public int? Index { get; set; } 38 | public bool IsNullable { get; set; } 39 | public string NullValue { get; set; } 40 | public ITypeConverter TypeConverter { get; set; } 41 | public PropertyInfo PropertyInfo { get; set; } 42 | } 43 | 44 | public class PropertySettingsContainer where TPropertySettings : IFieldSettings 45 | { 46 | public int Index { get; set; } 47 | public TPropertySettings PropertySettings { get; set; } 48 | } 49 | } -------------------------------------------------------------------------------- /src/FlatFile.Core/Base/FieldsContainer.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Core.Base 2 | { 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Reflection; 6 | 7 | public class AutoOrderedFieldsContainer : FieldsContainer 8 | where TFieldSettings : IFieldSettingsContainer 9 | { 10 | private int _currentPropertyId = 0; 11 | 12 | public override void AddOrUpdate(PropertyInfo propertyInfo, TFieldSettings settings) 13 | { 14 | settings.Index = _currentPropertyId++; 15 | 16 | base.AddOrUpdate(propertyInfo, settings); 17 | } 18 | } 19 | 20 | public class FieldsContainer : IFieldsContainer 21 | where TFieldSettings : IFieldSettings 22 | { 23 | protected Dictionary> Fields { get; private set; } 24 | 25 | public FieldsContainer() 26 | { 27 | Fields = new Dictionary>(); 28 | } 29 | 30 | public virtual void AddOrUpdate(PropertyInfo propertyInfo, TFieldSettings settings) 31 | { 32 | var propertySettings = new PropertySettingsContainer 33 | { 34 | PropertySettings = settings, 35 | Index = settings.Index.GetValueOrDefault() 36 | }; 37 | 38 | Fields[propertyInfo] = propertySettings; 39 | } 40 | 41 | public virtual IEnumerable OrderedFields 42 | { 43 | get 44 | { 45 | return Fields.Values 46 | .OrderBy(settings => settings.Index) 47 | .Select(x => x.PropertySettings) 48 | .AsEnumerable(); 49 | } 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /src/FlatFile.Core/Base/FlatFileEngine.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Core.Base 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | using FlatFile.Core; 7 | using FlatFile.Core.Exceptions; 8 | 9 | /// 10 | /// Class FlatFileEngine. 11 | /// 12 | /// The type of the t field settings. 13 | /// The type of the t layout descriptor. 14 | public abstract class FlatFileEngine : IFlatFileEngine 15 | where TFieldSettings : IFieldSettings 16 | where TLayoutDescriptor : ILayoutDescriptor 17 | { 18 | /// 19 | /// The handle entry read error func 20 | /// 21 | private readonly Func _handleEntryReadError; 22 | 23 | /// 24 | /// Gets the line builder. 25 | /// 26 | /// The line builder. 27 | protected abstract ILineBulder LineBuilder { get; } 28 | 29 | /// 30 | /// Gets the line parser. 31 | /// 32 | /// The line parser. 33 | protected abstract ILineParser LineParser { get; } 34 | 35 | /// 36 | /// Gets the layout descriptor. 37 | /// 38 | /// The layout descriptor. 39 | protected abstract TLayoutDescriptor LayoutDescriptor { get; } 40 | 41 | /// 42 | /// Initializes a new instance of the class. 43 | /// 44 | /// The handle entry read error. 45 | protected FlatFileEngine(Func handleEntryReadError = null) 46 | { 47 | _handleEntryReadError = handleEntryReadError; 48 | } 49 | 50 | /// 51 | /// Reads the specified stream. 52 | /// 53 | /// The type of the t entity. 54 | /// The stream. 55 | /// IEnumerable<TEntity>. 56 | /// Impossible to parse line 57 | public virtual IEnumerable Read(Stream stream) where TEntity : class, new() 58 | { 59 | var reader = new StreamReader(stream); 60 | string line; 61 | int lineNumber = 0; 62 | 63 | if (LayoutDescriptor.HasHeader) 64 | { 65 | ProcessHeader(reader); 66 | } 67 | 68 | while ((line = reader.ReadLine()) != null) 69 | { 70 | if (string.IsNullOrEmpty(line) || string.IsNullOrEmpty(line.Trim())) continue; 71 | 72 | bool ignoreEntry = false; 73 | var entry = new TEntity(); 74 | try 75 | { 76 | if (!TryParseLine(line, lineNumber++, ref entry)) 77 | { 78 | throw new ParseLineException("Impossible to parse line", line, lineNumber); 79 | } 80 | } 81 | catch (Exception ex) 82 | { 83 | if (_handleEntryReadError == null) 84 | { 85 | throw; 86 | } 87 | 88 | if (!_handleEntryReadError(line, ex)) 89 | { 90 | throw; 91 | } 92 | 93 | ignoreEntry = true; 94 | } 95 | 96 | if (!ignoreEntry) 97 | { 98 | yield return entry; 99 | } 100 | } 101 | } 102 | 103 | /// 104 | /// Processes the header. 105 | /// 106 | /// The reader. 107 | protected virtual void ProcessHeader(StreamReader reader) 108 | { 109 | reader.ReadLine(); 110 | } 111 | 112 | /// 113 | /// Tries to parse the line. 114 | /// 115 | /// The type of the t entity. 116 | /// The line. 117 | /// The line number. 118 | /// The entity. 119 | /// true if XXXX, false otherwise. 120 | protected virtual bool TryParseLine(string line, int lineNumber, ref TEntity entity) where TEntity : class, new() 121 | { 122 | LineParser.ParseLine(line, entity); 123 | 124 | return true; 125 | } 126 | 127 | /// 128 | /// Writes the entry. 129 | /// 130 | /// The type of the t entity. 131 | /// The writer. 132 | /// The line number. 133 | /// The entity. 134 | protected virtual void WriteEntry(TextWriter writer, int lineNumber, TEntity entity) 135 | { 136 | var line = LineBuilder.BuildLine(entity); 137 | 138 | writer.WriteLine(line); 139 | } 140 | 141 | /// 142 | /// Writes to the specified stream. 143 | /// 144 | /// The type of the t entity. 145 | /// The stream. 146 | /// The entries. 147 | public virtual void Write(Stream stream, IEnumerable entries) where TEntity : class, new() 148 | { 149 | TextWriter writer = new StreamWriter(stream); 150 | 151 | this.WriteHeader(writer); 152 | 153 | int lineNumber = 0; 154 | 155 | foreach (var entry in entries) 156 | { 157 | this.WriteEntry(writer, lineNumber, entry); 158 | 159 | lineNumber += 1; 160 | } 161 | 162 | this.WriteFooter(writer); 163 | 164 | writer.Flush(); 165 | } 166 | 167 | /// 168 | /// Writes the header. 169 | /// 170 | /// The writer. 171 | protected virtual void WriteHeader(TextWriter writer) 172 | { 173 | } 174 | 175 | /// 176 | /// Writes the footer. 177 | /// 178 | /// The writer. 179 | protected virtual void WriteFooter(TextWriter writer) 180 | { 181 | } 182 | } 183 | } -------------------------------------------------------------------------------- /src/FlatFile.Core/Base/LayoutBase.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Core.Base 2 | { 3 | using System; 4 | using System.Linq.Expressions; 5 | using System.Reflection; 6 | using FlatFile.Core.Extensions; 7 | 8 | public abstract class LayoutBase 9 | : LayoutDescriptorBase, ILayout 10 | where TFieldSettings : class, IFieldSettings 11 | where TConstructor : IFieldSettingsConstructor 12 | where TLayout : ILayout 13 | { 14 | private readonly IFieldSettingsFactory _fieldSettingsFactory; 15 | 16 | protected LayoutBase( 17 | IFieldSettingsFactory fieldSettingsFactory, 18 | IFieldsContainer fieldsContainer) : base(fieldsContainer) 19 | { 20 | this._fieldSettingsFactory = fieldSettingsFactory; 21 | } 22 | 23 | protected virtual void ProcessProperty(Expression> expression, Action settings) 24 | { 25 | var propertyInfo = GetPropertyInfo(expression); 26 | 27 | var constructor = _fieldSettingsFactory.CreateFieldSettings(propertyInfo); 28 | 29 | if (settings != null) 30 | { 31 | settings(constructor); 32 | } 33 | 34 | FieldsContainer.AddOrUpdate(constructor.PropertyInfo, constructor as TFieldSettings); 35 | } 36 | 37 | protected virtual PropertyInfo GetPropertyInfo(Expression> expression) 38 | { 39 | var propertyInfo = expression.GetPropertyInfo(); 40 | return propertyInfo; 41 | } 42 | 43 | public override Type TargetType { get { return typeof (TTarget); } } 44 | 45 | public abstract TLayout WithMember(Expression> expression, Action settings = null); 46 | 47 | public abstract TLayout WithHeader(); 48 | } 49 | } -------------------------------------------------------------------------------- /src/FlatFile.Core/Base/LayoutDescriptorBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace FlatFile.Core.Base 5 | { 6 | public class LayoutDescriptorBase : ILayoutDescriptor 7 | where TFieldSettings : IFieldSettings 8 | { 9 | protected IFieldsContainer FieldsContainer { get; private set; } 10 | 11 | public LayoutDescriptorBase(IFieldsContainer fieldsContainer) 12 | { 13 | FieldsContainer = fieldsContainer; 14 | } 15 | 16 | public LayoutDescriptorBase(IFieldsContainer fieldsContainer, Type targetType) : this(fieldsContainer) { TargetType = targetType; } 17 | 18 | public virtual Type TargetType { get; private set; } 19 | 20 | public IEnumerable Fields 21 | { 22 | get { return FieldsContainer.OrderedFields; } 23 | } 24 | 25 | public bool HasHeader { get; protected internal set; } 26 | } 27 | } -------------------------------------------------------------------------------- /src/FlatFile.Core/Base/LineBulderBase.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Core.Base 2 | { 3 | public abstract class LineBulderBase : ILineBulder 4 | where TLayoutDescriptor : ILayoutDescriptor 5 | where TFieldSettings : IFieldSettingsContainer 6 | { 7 | private readonly TLayoutDescriptor _descriptor; 8 | 9 | protected LineBulderBase(TLayoutDescriptor descriptor) 10 | { 11 | this._descriptor = descriptor; 12 | } 13 | 14 | protected TLayoutDescriptor Descriptor 15 | { 16 | get { return _descriptor; } 17 | } 18 | 19 | public abstract string BuildLine(T entry); 20 | 21 | protected virtual string GetStringValueFromField(TFieldSettings field, object fieldValue) 22 | { 23 | string lineValue = fieldValue != null 24 | ? fieldValue.ToString() 25 | : field.NullValue ?? string.Empty; 26 | 27 | lineValue = TransformFieldValue(field, lineValue); 28 | 29 | return lineValue; 30 | } 31 | 32 | protected virtual string TransformFieldValue(TFieldSettings field, string lineValue) 33 | { 34 | return lineValue; 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /src/FlatFile.Core/Base/LineParserBase.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Core.Base 2 | { 3 | using System; 4 | using FlatFile.Core.Extensions; 5 | 6 | public abstract class LineParserBase : ILineParser 7 | where TLayoutDescriptor : ILayoutDescriptor 8 | where TFieldSettings : IFieldSettingsContainer 9 | { 10 | private readonly TLayoutDescriptor _layout; 11 | 12 | protected LineParserBase(TLayoutDescriptor layout) 13 | { 14 | this._layout = layout; 15 | } 16 | 17 | protected TLayoutDescriptor Layout 18 | { 19 | get { return _layout; } 20 | } 21 | 22 | public abstract TEntity ParseLine(string line, TEntity entity) where TEntity : new(); 23 | 24 | protected virtual object GetFieldValueFromString(TFieldSettings fieldSettings, string memberValue) 25 | { 26 | if (fieldSettings.IsNullable && memberValue.Trim('"').Equals(fieldSettings.NullValue, StringComparison.InvariantCultureIgnoreCase)) 27 | { 28 | return null; 29 | } 30 | 31 | var type = fieldSettings.PropertyInfo.PropertyType; 32 | 33 | if (fieldSettings.IsNullablePropertyType()) 34 | { 35 | type = Nullable.GetUnderlyingType(fieldSettings.PropertyInfo.PropertyType); 36 | } 37 | 38 | memberValue = TransformStringValue(fieldSettings, memberValue); 39 | 40 | object obj; 41 | 42 | if (!fieldSettings.TypeConverter.ConvertFromStringTo(memberValue, type, out obj)) 43 | { 44 | obj = memberValue.Convert(type); 45 | } 46 | 47 | return obj; 48 | } 49 | 50 | protected virtual string TransformStringValue(TFieldSettings fieldSettingsBuilder, string memberValue) 51 | { 52 | return memberValue; 53 | } 54 | } 55 | 56 | public static class TypeConverterExtensions 57 | { 58 | 59 | public static bool ConvertFromStringTo(this ITypeConverter converter, string source, Type targetType, out object obj) 60 | { 61 | if (converter != null && converter.CanConvertFrom(typeof(string)) && converter.CanConvertTo(targetType)) 62 | { 63 | obj = converter.ConvertFromString(source); 64 | return true; 65 | } 66 | 67 | obj = null; 68 | 69 | return false; 70 | } 71 | } 72 | } -------------------------------------------------------------------------------- /src/FlatFile.Core/Exceptions/ParseLineException.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Core.Exceptions 2 | { 3 | using System; 4 | using System.Runtime.Serialization; 5 | 6 | [Serializable] 7 | public class ParseLineException : Exception 8 | { 9 | public ParseLineException(string message, Exception innerException, string line, int lineNumber) 10 | : base(message, innerException) 11 | { 12 | Line = line; 13 | LineNumber = lineNumber; 14 | } 15 | 16 | public ParseLineException(string message, string line, int lineNumber) 17 | : base(message) 18 | { 19 | Line = line; 20 | LineNumber = lineNumber; 21 | } 22 | 23 | public ParseLineException(string line, int lineNumber) 24 | { 25 | Line = line; 26 | LineNumber = lineNumber; 27 | } 28 | 29 | public int LineNumber { get; private set; } 30 | public string Line { get; private set; } 31 | 32 | protected ParseLineException(SerializationInfo info, StreamingContext context, string line, int lineNumber) 33 | : base(info, context) 34 | { 35 | Line = line; 36 | LineNumber = lineNumber; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/FlatFile.Core/Extensions/ExpressionExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Core.Extensions 2 | { 3 | using System; 4 | using System.Linq.Expressions; 5 | using System.Reflection; 6 | 7 | internal static class ExpressionExtensions 8 | { 9 | /// 10 | /// Gets the name of the member specified 11 | /// 12 | /// The type referenced 13 | /// The type of the member referenced 14 | /// The expression referencing the member 15 | /// The name of the member referenced by the expression 16 | public static string GetMemberName(this Expression> expression) 17 | { 18 | return expression.GetMemberExpression().Member.Name; 19 | } 20 | 21 | /// 22 | /// Gets the name of the member specified 23 | /// 24 | /// The type referenced 25 | /// The expression referencing the member 26 | /// The name of the member referenced by the expression 27 | public static string GetMemberName(this Expression> expression) 28 | { 29 | return expression.GetMemberExpression().Member.Name; 30 | } 31 | 32 | public static string GetMemberName(this Expression> expression) 33 | { 34 | return expression.GetMemberExpression().Member.Name; 35 | } 36 | 37 | public static PropertyInfo GetPropertyInfo(this Expression> expression) 38 | { 39 | return expression.GetMemberExpression().Member as PropertyInfo; 40 | } 41 | 42 | public static PropertyInfo GetPropertyInfo(this Expression> expression) 43 | { 44 | return expression.GetMemberExpression().Member as PropertyInfo; 45 | } 46 | 47 | public static MemberInfo GetMemberInfo(this Expression> expression) 48 | { 49 | return expression.GetMemberExpression().Member; 50 | } 51 | 52 | public static MemberExpression GetMemberExpression(this Expression> expression) 53 | { 54 | if (expression == null) 55 | throw new ArgumentNullException("expression"); 56 | 57 | return GetMemberExpression(expression.Body); 58 | } 59 | 60 | public static MemberExpression GetMemberExpression(this Expression> expression) 61 | { 62 | if (expression == null) 63 | throw new ArgumentNullException("expression"); 64 | return GetMemberExpression(expression.Body); 65 | } 66 | 67 | public static MemberExpression GetMemberExpression(this Expression> expression) 68 | { 69 | if (expression == null) 70 | throw new ArgumentNullException("expression"); 71 | return GetMemberExpression(expression.Body); 72 | } 73 | 74 | public static MemberExpression GetMemberExpression(this Expression> expression) 75 | { 76 | if (expression == null) 77 | throw new ArgumentNullException("expression"); 78 | 79 | return GetMemberExpression(expression.Body); 80 | } 81 | 82 | private static MemberExpression GetMemberExpression(Expression body) 83 | { 84 | if (body == null) 85 | throw new ArgumentNullException("body"); 86 | 87 | MemberExpression memberExpression = null; 88 | if (body.NodeType == ExpressionType.Convert) 89 | { 90 | var unaryExpression = (UnaryExpression)body; 91 | memberExpression = unaryExpression.Operand as MemberExpression; 92 | } 93 | else if (body.NodeType == ExpressionType.MemberAccess) 94 | memberExpression = body as MemberExpression; 95 | 96 | if (memberExpression == null) 97 | throw new ArgumentException("Expression is not a member access"); 98 | 99 | return memberExpression; 100 | } 101 | } 102 | } -------------------------------------------------------------------------------- /src/FlatFile.Core/Extensions/FieldsSettingsExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Core.Extensions 2 | { 3 | using System; 4 | using FlatFile.Core.Base; 5 | 6 | public static class FieldsSettingsExtensions 7 | { 8 | public static bool IsNullablePropertyType(this TFieldSettings fieldSettings) 9 | where TFieldSettings : IFieldSettingsContainer 10 | { 11 | return fieldSettings.PropertyInfo.PropertyType.IsGenericType 12 | && fieldSettings.PropertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>); 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /src/FlatFile.Core/Extensions/ReflectionHelper.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Reflection; 3 | 4 | namespace FlatFile.Core.Extensions 5 | { 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq.Expressions; 9 | 10 | /// 11 | /// Class ReflectionHelper. 12 | /// 13 | public static class ReflectionHelper 14 | { 15 | static readonly object CacheLock = new object(); 16 | static readonly Dictionary Cache = new Dictionary(); 17 | 18 | /// 19 | /// Creates an instance of type using the default constructor. 20 | /// 21 | /// 22 | /// if set to true [cached]. 23 | /// T. 24 | public static T CreateInstance(bool cached = false) { return (T) CreateInstance(typeof (T), cached); } 25 | 26 | /// 27 | /// Creates an instance of type using the default constructor. 28 | /// 29 | /// Type of the target. 30 | /// if set to true [cached]. 31 | /// System.Object. 32 | public static object CreateInstance(Type targetType, bool cached = false) 33 | { 34 | if (targetType == null) return null; 35 | 36 | var ctorInfo = targetType.GetConstructor(Type.EmptyTypes); 37 | 38 | return CreateInstance(ctorInfo, cached); 39 | } 40 | 41 | /// 42 | /// Creates an instance of type using the specified constructor parameters. 43 | /// 44 | /// Type of the target. 45 | /// if set to true [cached]. 46 | /// The constructor arguments. 47 | /// System.Object. 48 | public static object CreateInstance(Type targetType, bool cached = false, params object[] parameters) 49 | { 50 | if (targetType == null) return null; 51 | if (parameters == null || !parameters.Any()) return CreateInstance(targetType, cached); 52 | 53 | var ctorInfo = targetType.GetConstructor(parameters.Select(a => a.GetType()).ToArray()); 54 | 55 | return CreateInstance(ctorInfo, cached, parameters); 56 | } 57 | 58 | static object CreateInstance(ConstructorInfo ctorInfo, bool cached, object[] parameters = null) 59 | { 60 | if (ctorInfo == null) return null; 61 | var hasArguments = parameters != null && parameters.Any(); 62 | 63 | Delegate ctor; 64 | lock (CacheLock) 65 | { 66 | if (!Cache.TryGetValue(ctorInfo, out ctor) || !cached) 67 | { 68 | if (hasArguments) 69 | { 70 | var ctorArgs = ctorInfo.GetParameters().Select((param, index) => Expression.Parameter(param.ParameterType, String.Format("Param{0}", index))).ToArray(); 71 | // ReSharper disable once CoVariantArrayConversion 72 | ctor = Expression.Lambda(Expression.New(ctorInfo, ctorArgs), ctorArgs).Compile(); 73 | } 74 | else 75 | { 76 | ctor = Expression.Lambda(Expression.New(ctorInfo)).Compile(); 77 | } 78 | } 79 | 80 | if (cached) CacheCtor(ctorInfo, ctor); 81 | } 82 | return hasArguments ? ctor.DynamicInvoke(parameters) : ctor.DynamicInvoke(); 83 | } 84 | 85 | static void CacheCtor(ConstructorInfo key, Delegate ctor) { if (!Cache.ContainsKey(key)) Cache.Add(key, ctor); } 86 | } 87 | } -------------------------------------------------------------------------------- /src/FlatFile.Core/Extensions/TypeChangeExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Core.Extensions 2 | { 3 | using System; 4 | using System.ComponentModel; 5 | 6 | public static class TypeChangeExtensions 7 | { 8 | public static object Convert(this string input, Type targetType) 9 | { 10 | var converter = TypeDescriptor.GetConverter(targetType); 11 | if (converter != null) 12 | { 13 | return converter.ConvertFromString(input); 14 | } 15 | return targetType.GetDefaultValue(); 16 | } 17 | 18 | public static T Convert(this string input) 19 | { 20 | return (T) Convert(input, typeof (T)); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /src/FlatFile.Core/Extensions/TypeExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Core.Extensions 2 | { 3 | using System; 4 | using System.Linq.Expressions; 5 | 6 | public static class TypeExtensions 7 | { 8 | public static object GetDefaultValue(this Type type) 9 | { 10 | if (type == null) 11 | { 12 | throw new ArgumentNullException("type"); 13 | } 14 | 15 | // We want an Func which returns the default. 16 | // Create that expression here. 17 | Expression> e = Expression.Lambda>( 18 | // Have to convert to object. 19 | Expression.Convert( 20 | // The default value, always get what the *code* tells us. 21 | type.GetDefaultExpression(), typeof(object) 22 | ) 23 | ); 24 | 25 | // Compile and return the value. 26 | return e.Compile()(); 27 | } 28 | 29 | public static Expression GetDefaultExpression(this Type type) 30 | { 31 | if (type == null) 32 | { 33 | throw new ArgumentNullException("type"); 34 | } 35 | 36 | if (type.IsValueType) 37 | { 38 | return Expression.Constant(Activator.CreateInstance(type), type); 39 | } 40 | 41 | return Expression.Constant(null, type); 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /src/FlatFile.Core/IFieldSettingsConstructor.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Core 2 | { 3 | using FlatFile.Core.Base; 4 | 5 | public interface IFieldSettingsConstructor : IFieldSettingsContainer 6 | where TConstructor : IFieldSettingsConstructor 7 | { 8 | TConstructor AllowNull(string nullValue); 9 | TConstructor WithTypeConverter() where TConverter : ITypeConverter; 10 | } 11 | } -------------------------------------------------------------------------------- /src/FlatFile.Core/IFieldSettingsFactory.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Core 2 | { 3 | using System.Reflection; 4 | 5 | public interface IFieldSettingsFactory 6 | where TBuilder : IFieldSettingsConstructor 7 | { 8 | TBuilder CreateFieldSettings(PropertyInfo property); 9 | } 10 | } -------------------------------------------------------------------------------- /src/FlatFile.Core/IFieldsContainer.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Core 2 | { 3 | using System.Collections.Generic; 4 | using System.Reflection; 5 | using FlatFile.Core.Base; 6 | 7 | public interface IFieldsContainer 8 | where TFieldSettings : IFieldSettings 9 | { 10 | void AddOrUpdate(PropertyInfo propertyInfo, TFieldSettings settings); 11 | 12 | IEnumerable OrderedFields { get; } 13 | } 14 | } -------------------------------------------------------------------------------- /src/FlatFile.Core/IFlatFileEngine.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Core 2 | { 3 | using System.Collections.Generic; 4 | using System.IO; 5 | 6 | /// 7 | /// Interface IFlatFileEngine 8 | /// 9 | public interface IFlatFileEngine 10 | { 11 | /// 12 | /// Reads the specified stream. 13 | /// 14 | /// The type of the t entity. 15 | /// The stream. 16 | /// IEnumerable<TEntity>. 17 | IEnumerable Read(Stream stream) where TEntity : class, new(); 18 | 19 | /// 20 | /// Writes to the specified stream. 21 | /// 22 | /// The type of the t entity. 23 | /// The stream. 24 | /// The entries. 25 | void Write(Stream stream, IEnumerable entries) where TEntity : class, new(); 26 | } 27 | } -------------------------------------------------------------------------------- /src/FlatFile.Core/IFlatFileEngineFactory.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Core 2 | { 3 | using System; 4 | using FlatFile.Core.Base; 5 | 6 | /// 7 | /// Interface IFlatFileEngineFactory 8 | /// 9 | /// The type of the t descriptor. 10 | /// The type of the t field settings. 11 | public interface IFlatFileEngineFactory 12 | where TDescriptor : ILayoutDescriptor 13 | where TFieldSettings : IFieldSettings 14 | { 15 | /// 16 | /// Gets the . 17 | /// 18 | /// The descriptor. 19 | /// The handle entry read error func. 20 | /// IFlatFileEngine. 21 | IFlatFileEngine GetEngine(TDescriptor descriptor, Func handleEntryReadError = null); 22 | } 23 | } -------------------------------------------------------------------------------- /src/FlatFile.Core/IFlatFileMultiEngine.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.IO; 3 | 4 | namespace FlatFile.Core 5 | { 6 | /// 7 | /// Interface IFlatFileMultiEngine 8 | /// 9 | public interface IFlatFileMultiEngine : IFlatFileEngine 10 | { 11 | /// 12 | /// Reads the specified stream. 13 | /// 14 | /// The stream. 15 | void Read(Stream stream); 16 | /// 17 | /// Gets any records of type read by . 18 | /// 19 | /// 20 | /// IEnumerable<T>. 21 | IEnumerable GetRecords() where T : class, new(); 22 | /// 23 | /// Gets or sets a value indicating whether this instance has a file header. 24 | /// 25 | /// true if this instance has a file header; otherwise, false. 26 | bool HasHeader { get; set; } 27 | } 28 | } -------------------------------------------------------------------------------- /src/FlatFile.Core/ILayout.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Core 2 | { 3 | using System; 4 | using System.Linq.Expressions; 5 | using FlatFile.Core.Base; 6 | 7 | public interface ILayout : ILayoutDescriptor 8 | where TFieldSettings : IFieldSettings 9 | where TConstructor : IFieldSettingsConstructor 10 | where TLayout : ILayout 11 | { 12 | TLayout WithMember(Expression> expression, Action settings = null); 13 | 14 | TLayout WithHeader(); 15 | } 16 | } -------------------------------------------------------------------------------- /src/FlatFile.Core/ILayoutDescriptor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace FlatFile.Core 4 | { 5 | using System.Collections.Generic; 6 | using FlatFile.Core.Base; 7 | 8 | public interface ILayoutDescriptor 9 | where TFieldSettings : IFieldSettings 10 | { 11 | Type TargetType { get; } 12 | 13 | IEnumerable Fields { get; } 14 | 15 | bool HasHeader { get; } 16 | } 17 | } -------------------------------------------------------------------------------- /src/FlatFile.Core/ILineBuilderFactory.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Core 2 | { 3 | using FlatFile.Core.Base; 4 | 5 | public interface ILineBuilderFactory 6 | where TFieldSettings : IFieldSettings 7 | where TLayout : ILayoutDescriptor 8 | where TBuilder : ILineBulder 9 | { 10 | TBuilder GetBuilder(TLayout layout); 11 | } 12 | } -------------------------------------------------------------------------------- /src/FlatFile.Core/ILineBulder.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Core 2 | { 3 | public interface ILineBulder 4 | { 5 | string BuildLine(T entry); 6 | } 7 | } -------------------------------------------------------------------------------- /src/FlatFile.Core/ILineParser.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Core 2 | { 3 | public interface ILineParser 4 | { 5 | TEntity ParseLine(string line, TEntity entity) where TEntity : new(); 6 | } 7 | } -------------------------------------------------------------------------------- /src/FlatFile.Core/ILineParserFactory.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Core 2 | { 3 | using FlatFile.Core.Base; 4 | 5 | public interface ILineParserFactory 6 | where TLayoutDescriptor : ILayoutDescriptor 7 | where TFieldSettings : IFieldSettings 8 | where TParser : ILineParser 9 | { 10 | TParser GetParser(TLayoutDescriptor descriptor); 11 | } 12 | } -------------------------------------------------------------------------------- /src/FlatFile.Core/ITypeConverter.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Core 2 | { 3 | using System; 4 | 5 | public interface ITypeConverter 6 | { 7 | bool CanConvertFrom(Type type); 8 | 9 | bool CanConvertTo(Type type); 10 | 11 | string ConvertToString(object source); 12 | 13 | object ConvertFromString(string source); 14 | } 15 | } -------------------------------------------------------------------------------- /src/FlatFile.Core/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("FlatFile.Core")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("EPAM Systems")] 12 | [assembly: AssemblyProduct("FlatFile.Core")] 13 | [assembly: AssemblyCopyright("Copyright © EPAM Systems 2014")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("f2c28e66-9e85-4264-a4c5-95a6a5f772a1")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | 38 | [assembly: InternalsVisibleTo("FlatFile.Tests")] 39 | [assembly: InternalsVisibleTo("FlatFile.FixedLength.Attributes")] 40 | [assembly: InternalsVisibleTo("FlatFile.FixedLength")] 41 | [assembly: InternalsVisibleTo("FlatFile.Delimited.Attributes")] 42 | [assembly: InternalsVisibleTo("FlatFile.Delimited")] 43 | [assembly: InternalsVisibleTo("FlatFile.Core.Attributes")] 44 | -------------------------------------------------------------------------------- /src/FlatFile.Delimited.Attributes/DelimitedFieldAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Delimited.Attributes 2 | { 3 | using FlatFile.Core.Attributes.Base; 4 | 5 | public class DelimitedFieldAttribute : FieldSettingsBaseAttribute, IDelimitedFieldSettings 6 | { 7 | public string Name { get; set; } 8 | 9 | public DelimitedFieldAttribute(int index) : base(index) 10 | { 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/FlatFile.Delimited.Attributes/DelimitedFileAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Delimited.Attributes 2 | { 3 | using FlatFile.Core.Attributes.Base; 4 | 5 | public class DelimitedFileAttribute : LayoutBaseAttribute 6 | { 7 | public string Delimiter { get; set; } 8 | public string Quotes { get; set; } 9 | } 10 | } -------------------------------------------------------------------------------- /src/FlatFile.Delimited.Attributes/FlatFileEngineFactoryExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using FlatFile.Delimited.Implementation; 4 | 5 | namespace FlatFile.Delimited.Attributes 6 | { 7 | using System; 8 | using FlatFile.Core; 9 | using FlatFile.Delimited; 10 | using FlatFile.Delimited.Attributes.Infrastructure; 11 | 12 | public static class FlatFileEngineFactoryExtensions 13 | { 14 | /// 15 | /// Gets the engine. 16 | /// 17 | /// The type of the t entity. 18 | /// The engine factory. 19 | /// The handle entry read error. 20 | /// IFlatFileEngine. 21 | public static IFlatFileEngine GetEngine( 22 | this IFlatFileEngineFactory engineFactory, 23 | Func handleEntryReadError = null) 24 | where TEntity : class, new() 25 | { 26 | var descriptorProvider = new DelimitedLayoutDescriptorProvider(); 27 | 28 | var descriptor = descriptorProvider.GetDescriptor(); 29 | 30 | return engineFactory.GetEngine(descriptor, handleEntryReadError); 31 | } 32 | 33 | /// 34 | /// Gets the engine. 35 | /// 36 | /// The engine factory. 37 | /// The record types. 38 | /// The type selector function. 39 | /// The handle entry read error. 40 | /// IFlatFileMultiEngine. 41 | public static IFlatFileMultiEngine GetEngine( 42 | this DelimitedFileEngineFactory engineFactory, 43 | IEnumerable recordTypes, 44 | Func typeSelectorFunc, 45 | Func handleEntryReadError = null) 46 | { 47 | var descriptorProvider = new DelimitedLayoutDescriptorProvider(); 48 | var descriptors = recordTypes.Select(type => descriptorProvider.GetDescriptor(type)).ToList(); 49 | return engineFactory.GetEngine(descriptors, typeSelectorFunc, handleEntryReadError); 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /src/FlatFile.Delimited.Attributes/Infrastructure/DelimitedLayoutDescriptorProvider.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Delimited.Attributes.Infrastructure 2 | { 3 | using System; 4 | using System.Linq; 5 | using FlatFile.Core; 6 | using FlatFile.Core.Attributes.Extensions; 7 | using FlatFile.Core.Attributes.Infrastructure; 8 | using FlatFile.Core.Base; 9 | using FlatFile.Delimited.Implementation; 10 | 11 | 12 | public class DelimitedLayoutDescriptorProvider : ILayoutDescriptorProvider 13 | { 14 | public IDelimitedLayoutDescriptor GetDescriptor() 15 | { 16 | return GetDescriptor(typeof(T)); 17 | } 18 | 19 | public IDelimitedLayoutDescriptor GetDescriptor(Type t) 20 | { 21 | var container = new FieldsContainer(); 22 | 23 | var fileMappingType = t; 24 | 25 | var fileAttribute = fileMappingType.GetAttribute(); 26 | 27 | if (fileAttribute == null) 28 | { 29 | throw new NotSupportedException(string.Format("Mapping type {0} should be marked with {1} attribute", 30 | fileMappingType.Name, 31 | typeof(DelimitedFileAttribute).Name)); 32 | } 33 | 34 | var properties = fileMappingType.GetTypeDescription(); 35 | 36 | foreach (var p in properties) 37 | { 38 | var settings = p.Attributes.FirstOrDefault() as IDelimitedFieldSettings; 39 | 40 | if (settings != null) 41 | { 42 | container.AddOrUpdate(p.Property, new DelimitedFieldSettings(p.Property, settings)); 43 | } 44 | } 45 | 46 | 47 | var methodInfo = typeof(DelimedLayoutGeneric) 48 | .GetMethod("GetDelimitedLayout") 49 | .MakeGenericMethod(new[] { t }); 50 | object[] args = { null, new DelimitedFieldSettingsFactory(), container, fileAttribute }; 51 | var descriptor = (IDelimitedLayoutDescriptor)methodInfo.Invoke(null, args); 52 | 53 | //var descriptor = DelimedLayoutGeneric.GetDelimitedLayout(t, new DelimitedFieldSettingsFactory(), container) 54 | // .WithDelimiter(fileAttribute.Delimiter) 55 | // .WithQuote(fileAttribute.Quotes); 56 | 57 | //if (fileAttribute.HasHeader) 58 | //{ 59 | // descriptor.WithHeader(); 60 | //} 61 | 62 | return descriptor; 63 | } 64 | } 65 | 66 | public class DelimedLayoutGeneric 67 | { 68 | public static IDelimitedLayoutDescriptor GetDelimitedLayout(TTarget t, 69 | IFieldSettingsFactory fieldSettingsFactory, 70 | IFieldsContainer fieldsContainer, 71 | DelimitedFileAttribute fileAttribute) 72 | { 73 | var dl = new DelimitedLayout(fieldSettingsFactory, fieldsContainer) 74 | .WithDelimiter(fileAttribute.Delimiter) 75 | .WithQuote(fileAttribute.Quotes); 76 | 77 | if (fileAttribute.HasHeader) 78 | { 79 | dl.WithHeader(); 80 | } 81 | 82 | return dl; 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/FlatFile.Delimited.Attributes/Infrastructure/DelimitedMultiLayoutDescriptor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using FlatFile.Core; 5 | using FlatFile.Core.Base; 6 | using FlatFile.Core.Attributes.Extensions; 7 | using FlatFile.Core.Attributes.Infrastructure; 8 | 9 | namespace FlatFile.Delimited.Attributes.Infrastructure 10 | { 11 | public class DelimitedMultiLayoutDescriptor : ILayoutDescriptorProvider> 12 | where TFieldSettings : IDelimitedFieldSettingsContainer 13 | { 14 | protected IFieldsContainer FieldsContainer { get; private set; } 15 | 16 | public DelimitedMultiLayoutDescriptor(IFieldsContainer fieldsContainer) 17 | { 18 | FieldsContainer = fieldsContainer; 19 | } 20 | 21 | public DelimitedMultiLayoutDescriptor(IFieldsContainer fieldsContainer, Type targetType) : this(fieldsContainer) { TargetType = targetType; } 22 | 23 | ILayoutDescriptor ILayoutDescriptorProvider>.GetDescriptor() 24 | { 25 | throw new NotImplementedException(); 26 | } 27 | 28 | public virtual Type TargetType { get; private set; } 29 | 30 | public IEnumerable Fields 31 | { 32 | get { return FieldsContainer.OrderedFields; } 33 | } 34 | 35 | public bool HasHeader { get; protected internal set; } 36 | 37 | 38 | public string Delimiter { get; private set; } 39 | 40 | public string Quotes { get; private set; } 41 | 42 | public DelimitedMultiLayoutDescriptor WithQuote(string quote) 43 | { 44 | Quotes = quote; 45 | 46 | return this; 47 | } 48 | 49 | public DelimitedMultiLayoutDescriptor WithDelimiter(string delimiter) 50 | { 51 | Delimiter = delimiter; 52 | 53 | return this; 54 | } 55 | 56 | 57 | } 58 | } -------------------------------------------------------------------------------- /src/FlatFile.Delimited.Attributes/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("FlatFile.Delimited.Attributes")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("FlatFile.Delimited.Attributes")] 13 | [assembly: AssemblyCopyright("Copyright © 2014")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("6d2ff0a0-9c37-4179-a59f-304f44d79d69")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/FlatFile.Delimited/DelimitedFieldSettings.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Delimited 2 | { 3 | using System.Reflection; 4 | using FlatFile.Core.Base; 5 | 6 | public interface IDelimitedFieldSettings : IFieldSettings 7 | { 8 | string Name { get; set; } 9 | } 10 | 11 | public interface IDelimitedFieldSettingsContainer : IDelimitedFieldSettings, IFieldSettingsContainer 12 | { 13 | } 14 | 15 | public class DelimitedFieldSettings : FieldSettingsBase, IDelimitedFieldSettingsContainer 16 | { 17 | public DelimitedFieldSettings(PropertyInfo propertyInfo) : base(propertyInfo) 18 | { 19 | } 20 | 21 | public DelimitedFieldSettings(IDelimitedFieldSettings settings) 22 | : base(settings) 23 | { 24 | Name = settings.Name; 25 | TypeConverter = settings.TypeConverter; 26 | } 27 | 28 | public DelimitedFieldSettings(PropertyInfo propertyInfo, IDelimitedFieldSettings settings) 29 | : this(settings) 30 | { 31 | PropertyInfo = propertyInfo; 32 | } 33 | 34 | public string Name { get; set; } 35 | } 36 | } -------------------------------------------------------------------------------- /src/FlatFile.Delimited/IDelimitedFieldSettingsConstructor.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Delimited 2 | { 3 | using FlatFile.Core; 4 | 5 | public interface IDelimitedFieldSettingsConstructor : 6 | IFieldSettingsConstructor 7 | { 8 | string Name { get; } 9 | 10 | IDelimitedFieldSettingsConstructor WithName(string name); 11 | } 12 | } -------------------------------------------------------------------------------- /src/FlatFile.Delimited/IDelimitedLayout.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Delimited 2 | { 3 | using FlatFile.Core; 4 | 5 | public interface IDelimitedLayout : 6 | IDelimitedLayoutDescriptor, 7 | ILayout> 8 | { 9 | IDelimitedLayout WithQuote(string quote); 10 | IDelimitedLayout WithDelimiter(string delimiter); 11 | } 12 | } -------------------------------------------------------------------------------- /src/FlatFile.Delimited/IDelimitedLayoutDescriptor.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Delimited 2 | { 3 | using FlatFile.Core; 4 | 5 | public interface IDelimitedLayoutDescriptor : ILayoutDescriptor 6 | { 7 | string Delimiter { get; } 8 | string Quotes { get; } 9 | } 10 | } -------------------------------------------------------------------------------- /src/FlatFile.Delimited/IDelimitedLineBuilder.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Delimited 2 | { 3 | using FlatFile.Core; 4 | 5 | public interface IDelimitedLineBuilder : ILineBulder 6 | { 7 | } 8 | } -------------------------------------------------------------------------------- /src/FlatFile.Delimited/IDelimitedLineBuilderFactory.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Delimited 2 | { 3 | using FlatFile.Core; 4 | 5 | public interface IDelimitedLineBuilderFactory : 6 | ILineBuilderFactory 7 | { 8 | } 9 | } -------------------------------------------------------------------------------- /src/FlatFile.Delimited/IDelimitedLineParser.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Delimited 2 | { 3 | using FlatFile.Core; 4 | 5 | public interface IDelimitedLineParser : ILineParser 6 | { 7 | } 8 | } -------------------------------------------------------------------------------- /src/FlatFile.Delimited/IDelimitedLineParserFactory.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Delimited 2 | { 3 | using FlatFile.Core; 4 | 5 | public interface IDelimitedLineParserFactory : 6 | ILineParserFactory 7 | { 8 | } 9 | } -------------------------------------------------------------------------------- /src/FlatFile.Delimited/IDetailRecord.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Delimited 2 | { 3 | /// 4 | /// Interface IDetailRecord 5 | /// 6 | /// 7 | /// Used to decorate a record as a detail type in a master/detail relationship 8 | /// 9 | public interface IDetailRecord 10 | { 11 | } 12 | } -------------------------------------------------------------------------------- /src/FlatFile.Delimited/IMasterRecord.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using FlatFile.Core; 3 | 4 | namespace FlatFile.Delimited 5 | { 6 | /// 7 | /// Interface IMasterRecord 8 | /// 9 | /// 10 | /// Used to decorate a record as a master type in a master/detail relationship. 11 | /// 12 | public interface IMasterRecord 13 | { 14 | /// 15 | /// Gets the detail records. 16 | /// 17 | /// The detail records. 18 | /// 19 | /// This list will be populated with related detail records when parsing a fixed length file with the 20 | /// 21 | IList DetailRecords { get; } 22 | } 23 | } -------------------------------------------------------------------------------- /src/FlatFile.Delimited/Implementation/DelimitedFieldSettingsConstructor.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Delimited.Implementation 2 | { 3 | using System.Reflection; 4 | using FlatFile.Core; 5 | using FlatFile.Core.Extensions; 6 | 7 | public class DelimitedFieldSettingsConstructor : 8 | DelimitedFieldSettings, 9 | IDelimitedFieldSettingsConstructor 10 | { 11 | public DelimitedFieldSettingsConstructor(PropertyInfo propertyInfo) : base(propertyInfo) 12 | { 13 | } 14 | 15 | public IDelimitedFieldSettingsConstructor AllowNull(string nullValue) 16 | { 17 | this.IsNullable = true; 18 | this.NullValue = nullValue; 19 | return this; 20 | } 21 | 22 | public IDelimitedFieldSettingsConstructor WithTypeConverter() where TConverter : ITypeConverter 23 | { 24 | this.TypeConverter = ReflectionHelper.CreateInstance(true); 25 | return this; 26 | } 27 | 28 | public IDelimitedFieldSettingsConstructor WithName(string name) 29 | { 30 | Name = name; 31 | return this; 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /src/FlatFile.Delimited/Implementation/DelimitedFieldSettingsFactory.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Delimited.Implementation 2 | { 3 | using System.Reflection; 4 | using FlatFile.Core; 5 | 6 | public class DelimitedFieldSettingsFactory : 7 | IFieldSettingsFactory 8 | { 9 | public IDelimitedFieldSettingsConstructor CreateFieldSettings(PropertyInfo property) 10 | { 11 | return new DelimitedFieldSettingsConstructor(property); 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /src/FlatFile.Delimited/Implementation/DelimitedFileEngine.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Delimited.Implementation 2 | { 3 | using System; 4 | using System.IO; 5 | using System.Text; 6 | using FlatFile.Core; 7 | using FlatFile.Core.Base; 8 | 9 | /// 10 | /// Class DelimitedFileEngine. 11 | /// 12 | public class DelimitedFileEngine : 13 | FlatFileEngine 14 | { 15 | /// 16 | /// The line builder factory 17 | /// 18 | private readonly IDelimitedLineBuilderFactory _builderFactory; 19 | 20 | /// 21 | /// The line parser factory 22 | /// 23 | private readonly IDelimitedLineParserFactory _parserFactory; 24 | 25 | /// 26 | /// The layout descriptor 27 | /// 28 | private readonly IDelimitedLayoutDescriptor _layoutDescriptor; 29 | 30 | /// 31 | /// Initializes a new instance of the class. 32 | /// 33 | /// The layout descriptor. 34 | /// The builder factory. 35 | /// The parser factory. 36 | /// The handle entry read error. 37 | internal DelimitedFileEngine( 38 | IDelimitedLayoutDescriptor layoutDescriptor, 39 | IDelimitedLineBuilderFactory builderFactory, 40 | IDelimitedLineParserFactory parserFactory, 41 | Func handleEntryReadError = null) 42 | : base(handleEntryReadError) 43 | { 44 | _builderFactory = builderFactory; 45 | _parserFactory = parserFactory; 46 | _layoutDescriptor = layoutDescriptor; 47 | } 48 | 49 | /// 50 | /// Gets the line builder. 51 | /// 52 | /// The line builder. 53 | protected override ILineBulder LineBuilder 54 | { 55 | get { return _builderFactory.GetBuilder(LayoutDescriptor); } 56 | } 57 | 58 | /// 59 | /// Gets the line parser. 60 | /// 61 | /// The line parser. 62 | protected override ILineParser LineParser 63 | { 64 | get { return _parserFactory.GetParser(LayoutDescriptor); } 65 | } 66 | 67 | /// 68 | /// Gets the layout descriptor. 69 | /// 70 | /// The layout descriptor. 71 | protected override IDelimitedLayoutDescriptor LayoutDescriptor 72 | { 73 | get { return _layoutDescriptor; } 74 | } 75 | 76 | /// 77 | /// Writes the header. 78 | /// 79 | /// The writer. 80 | protected override void WriteHeader(TextWriter writer) 81 | { 82 | if (!LayoutDescriptor.HasHeader) 83 | { 84 | return; 85 | } 86 | 87 | var fields = LayoutDescriptor.Fields; 88 | 89 | var stringBuilder = new StringBuilder(); 90 | 91 | foreach (var field in fields) 92 | { 93 | stringBuilder 94 | .Append(field.Name) 95 | .Append(LayoutDescriptor.Delimiter); 96 | 97 | } 98 | 99 | stringBuilder.Remove(stringBuilder.Length - 1, 1); 100 | 101 | writer.WriteLine(stringBuilder.ToString()); 102 | } 103 | } 104 | } -------------------------------------------------------------------------------- /src/FlatFile.Delimited/Implementation/DelimitedFileEngineFactory.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using FlatFile.Core.Base; 3 | 4 | namespace FlatFile.Delimited.Implementation 5 | { 6 | using System; 7 | using FlatFile.Core; 8 | 9 | /// 10 | /// Class DelimitedFileEngineFactory. 11 | /// 12 | public class DelimitedFileEngineFactory : 13 | IFlatFileEngineFactory 14 | { 15 | 16 | readonly DelimitedLineParserFactory lineParserFactory = new DelimitedLineParserFactory(); 17 | 18 | /// 19 | /// Registers the line parser for lines matching . 20 | /// 21 | /// The type of the t parser. 22 | /// The target record type. 23 | /// 24 | public void RegisterLineParser(Type targetType) where TParser : IDelimitedLineParser 25 | { 26 | lineParserFactory.RegisterLineParser(targetType); 27 | } 28 | 29 | /// 30 | /// Registers the line parser for lines matching . 31 | /// 32 | /// The type of the t parser. 33 | /// The target layout. 34 | /// 35 | public void RegisterLineParser(ILayoutDescriptor targetLayout) where TParser : IDelimitedLineParser 36 | { 37 | lineParserFactory.RegisterLineParser(targetLayout); 38 | } 39 | 40 | /// 41 | /// Gets the . 42 | /// 43 | /// The descriptor. 44 | /// The handle entry read error func. 45 | /// IFlatFileEngine. 46 | public IFlatFileEngine GetEngine( 47 | IDelimitedLayoutDescriptor descriptor, 48 | Func handleEntryReadError = null) 49 | { 50 | return new DelimitedFileEngine( 51 | descriptor, 52 | new DelimitedLineBuilderFactory(), 53 | new DelimitedLineParserFactory(), 54 | handleEntryReadError); 55 | } 56 | 57 | 58 | 59 | /// 60 | /// Gets the . 61 | /// 62 | /// The layout descriptors. 63 | /// The type selector function. 64 | /// The handle entry read error func. 65 | /// IFlatFileMultiEngine. 66 | public IFlatFileMultiEngine GetEngine( 67 | IEnumerable layoutDescriptors, 68 | Func typeSelectorFunc, 69 | Func handleEntryReadError = null) 70 | { 71 | return new DelimitedFileMultiEngine( 72 | layoutDescriptors, 73 | typeSelectorFunc, 74 | new DelimitedLineBuilderFactory(), 75 | lineParserFactory, 76 | handleEntryReadError); 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/FlatFile.Delimited/Implementation/DelimitedLayout.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Delimited.Implementation 2 | { 3 | using System; 4 | using System.Linq.Expressions; 5 | using FlatFile.Core; 6 | using FlatFile.Core.Base; 7 | 8 | public class DelimitedLayout : 9 | LayoutBase>, 10 | IDelimitedLayout 11 | { 12 | public DelimitedLayout() 13 | : this( 14 | new DelimitedFieldSettingsFactory(), 15 | new FieldsContainer()) 16 | { 17 | } 18 | 19 | public DelimitedLayout( 20 | IFieldSettingsFactory fieldSettingsFactory, 21 | IFieldsContainer fieldsContainer) 22 | : base(fieldSettingsFactory, fieldsContainer) 23 | { 24 | Quotes = string.Empty; 25 | Delimiter = ","; 26 | } 27 | 28 | public string Delimiter { get; private set; } 29 | 30 | public string Quotes { get; private set; } 31 | 32 | public IDelimitedLayout WithQuote(string quote) 33 | { 34 | Quotes = quote; 35 | 36 | return this; 37 | } 38 | 39 | public IDelimitedLayout WithDelimiter(string delimiter) 40 | { 41 | Delimiter = delimiter; 42 | 43 | return this; 44 | } 45 | 46 | public override IDelimitedLayout WithMember( 47 | Expression> expression, 48 | Action settings = null) 49 | { 50 | ProcessProperty(expression, settings); 51 | 52 | return this; 53 | } 54 | 55 | public override IDelimitedLayout WithHeader() 56 | { 57 | HasHeader = true; 58 | 59 | return this; 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /src/FlatFile.Delimited/Implementation/DelimitedLineBuilder.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Delimited.Implementation 2 | { 3 | using System.Linq; 4 | using FlatFile.Core.Base; 5 | 6 | public class DelimitedLineBuilder : 7 | LineBulderBase, 8 | IDelimitedLineBuilder 9 | { 10 | public DelimitedLineBuilder(IDelimitedLayoutDescriptor descriptor) 11 | : base(descriptor) 12 | { 13 | } 14 | 15 | public override string BuildLine(T entry) 16 | { 17 | string line = Descriptor.Fields.Aggregate(string.Empty, 18 | (current, field) => 19 | current + (current.Length > 0 ? Descriptor.Delimiter : "") + 20 | GetStringValueFromField(field, field.PropertyInfo.GetValue(entry, null))); 21 | return line; 22 | } 23 | 24 | protected override string TransformFieldValue(IDelimitedFieldSettingsContainer field, string lineValue) 25 | { 26 | var quotes = Descriptor.Quotes; 27 | if (!string.IsNullOrEmpty(quotes)) 28 | { 29 | lineValue = string.Format("{0}{1}{0}", quotes, lineValue); 30 | } 31 | return lineValue; 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /src/FlatFile.Delimited/Implementation/DelimitedLineBuilderFactory.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Delimited.Implementation 2 | { 3 | public class DelimitedLineBuilderFactory : IDelimitedLineBuilderFactory 4 | { 5 | public IDelimitedLineBuilder GetBuilder(IDelimitedLayoutDescriptor descriptor) 6 | { 7 | return new DelimitedLineBuilder(descriptor); 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /src/FlatFile.Delimited/Implementation/DelimitedLineParser.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Delimited.Implementation 2 | { 3 | using System; 4 | using FlatFile.Core; 5 | using FlatFile.Core.Base; 6 | 7 | public class DelimitedLineParser : 8 | LineParserBase, 9 | IDelimitedLineParser 10 | 11 | { 12 | public DelimitedLineParser(IDelimitedLayoutDescriptor layout) 13 | : base(layout) 14 | { 15 | } 16 | 17 | 18 | public override TEntity ParseLine(string line, TEntity entity) 19 | { 20 | 21 | int linePosition = 0; 22 | int delimiterSize = Layout.Delimiter.Length; 23 | foreach (var field in Layout.Fields) 24 | { 25 | int nextDelimiterIndex = -1; 26 | if (line.Length > linePosition + delimiterSize) 27 | { 28 | if (!String.IsNullOrEmpty(Layout.Quotes)) { 29 | if (Layout.Quotes.Equals(line.Substring(linePosition, Layout.Quotes.Length))) 30 | { 31 | nextDelimiterIndex = line.IndexOf(Layout.Quotes, linePosition + 1, StringComparison.InvariantCultureIgnoreCase); 32 | if (line.Length > nextDelimiterIndex) 33 | { 34 | nextDelimiterIndex = line.IndexOf(Layout.Delimiter, nextDelimiterIndex, StringComparison.InvariantCultureIgnoreCase); 35 | } 36 | } 37 | } 38 | 39 | if (nextDelimiterIndex == -1) 40 | { 41 | nextDelimiterIndex = line.IndexOf(Layout.Delimiter, linePosition, StringComparison.InvariantCultureIgnoreCase); 42 | } 43 | } 44 | int fieldLength; 45 | if (nextDelimiterIndex > -1) 46 | { 47 | fieldLength = nextDelimiterIndex - linePosition; 48 | } 49 | else 50 | { 51 | fieldLength = line.Length - linePosition; 52 | } 53 | string fieldValueFromLine = line.Substring(linePosition, fieldLength); 54 | var convertedFieldValue = GetFieldValueFromString(field, fieldValueFromLine); 55 | field.PropertyInfo.SetValue(entity, convertedFieldValue, null); 56 | linePosition += fieldLength + (nextDelimiterIndex > -1 ? delimiterSize : 0); 57 | } 58 | return entity; 59 | } 60 | 61 | protected override string TransformStringValue(IDelimitedFieldSettingsContainer fieldSettingsBuilder, string memberValue) 62 | { 63 | if (string.IsNullOrEmpty(Layout.Quotes)) 64 | { 65 | return memberValue; 66 | } 67 | 68 | var value = memberValue.Replace(Layout.Quotes, String.Empty); 69 | return value; 70 | } 71 | } 72 | } -------------------------------------------------------------------------------- /src/FlatFile.Delimited/Implementation/DelimitedLineParserFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using FlatFile.Core; 5 | using FlatFile.Core.Base; 6 | using FlatFile.Core.Extensions; 7 | 8 | namespace FlatFile.Delimited.Implementation 9 | { 10 | public class DelimitedLineParserFactory : IDelimitedLineParserFactory 11 | { 12 | readonly Dictionary lineParserRegistry; 13 | 14 | /// 15 | /// Initializes a new instance of the class. 16 | /// 17 | public DelimitedLineParserFactory() { lineParserRegistry = new Dictionary(); } 18 | 19 | /// 20 | /// Initializes a new instance of the class. 21 | /// 22 | /// The line parser registry. 23 | public DelimitedLineParserFactory(IDictionary lineParserRegistry) { this.lineParserRegistry = new Dictionary(lineParserRegistry); } 24 | 25 | /// 26 | /// Initializes a new instance of the class. 27 | /// 28 | /// The line parser registry. 29 | public DelimitedLineParserFactory(IDictionary> lineParserRegistry) 30 | { 31 | this.lineParserRegistry = lineParserRegistry.ToDictionary(descriptor => descriptor.Key, descriptor => descriptor.Value.TargetType); 32 | } 33 | 34 | public IDelimitedLineParser GetParser(IDelimitedLayoutDescriptor descriptor) 35 | { 36 | return new DelimitedLineParser(descriptor); 37 | } 38 | 39 | /// 40 | /// Gets the parser. 41 | /// 42 | /// The descriptor. 43 | /// IFixedLengthLineParser. 44 | public IDelimitedLineParser GetParser(ILayoutDescriptor descriptor) 45 | { 46 | if (descriptor == null) throw new ArgumentNullException("descriptor"); 47 | 48 | if (!(descriptor is IDelimitedLayoutDescriptor)) throw new ArgumentException("descriptor must be IDelimitedLayoutDescriptor"); 49 | 50 | return descriptor.TargetType != null && lineParserRegistry.ContainsKey(descriptor.TargetType) 51 | ? (IDelimitedLineParser)ReflectionHelper.CreateInstance(lineParserRegistry[descriptor.TargetType], true, descriptor) 52 | : new DelimitedLineParser((IDelimitedLayoutDescriptor)descriptor); 53 | } 54 | 55 | /// 56 | /// Registers the line parser for lines matching . 57 | /// 58 | /// The type of the t parser. 59 | /// The target record type. 60 | public void RegisterLineParser(Type targetType) where TParser : IDelimitedLineParser 61 | { 62 | lineParserRegistry[targetType] = typeof(TParser); 63 | } 64 | 65 | /// 66 | /// Registers the line parser for lines matching . 67 | /// 68 | /// The type of the t parser. 69 | /// The target layout. 70 | public void RegisterLineParser(ILayoutDescriptor targetLayout) where TParser : IDelimitedLineParser 71 | { 72 | lineParserRegistry[targetLayout.TargetType] = typeof(TParser); 73 | } 74 | 75 | } 76 | } -------------------------------------------------------------------------------- /src/FlatFile.Delimited/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("FlatFile.Delimited")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("EPAM Systems")] 12 | [assembly: AssemblyProduct("FlatFile.Delimited")] 13 | [assembly: AssemblyCopyright("Copyright © EPAM Systems 2014")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("d4d0ebc5-db19-42f6-b89b-13eb214ffcdf")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | [assembly: InternalsVisibleTo("FlatFile.Tests")] 38 | -------------------------------------------------------------------------------- /src/FlatFile.FixedLength.Attributes/FixedLengthFieldAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.FixedLength.Attributes 2 | { 3 | using System; 4 | using FlatFile.Core.Attributes.Base; 5 | 6 | public class FixedLengthFieldAttribute : FieldSettingsBaseAttribute, IFixedFieldSettings 7 | { 8 | public int Length { get; protected set; } 9 | 10 | public Padding Padding { get; set; } 11 | 12 | public bool PadLeft 13 | { 14 | get { return Padding == Padding.Left; } 15 | } 16 | 17 | public char PaddingChar { get; set; } 18 | 19 | public bool TruncateIfExceedFieldLength { get; set; } 20 | 21 | public Func StringNormalizer { get; set; } 22 | 23 | public FixedLengthFieldAttribute(int index, int length, bool truncateIfExceed = false) 24 | : base(index) 25 | { 26 | Padding = Padding.Left; 27 | TruncateIfExceedFieldLength = truncateIfExceed; 28 | Length = length; 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /src/FlatFile.FixedLength.Attributes/FixedLengthFileAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.FixedLength.Attributes 2 | { 3 | using FlatFile.Core.Attributes.Base; 4 | 5 | public class FixedLengthFileAttribute : LayoutBaseAttribute 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/FlatFile.FixedLength.Attributes/FlatFileEngineFactoryExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using FlatFile.FixedLength.Implementation; 4 | 5 | namespace FlatFile.FixedLength.Attributes 6 | { 7 | using System; 8 | using FlatFile.Core; 9 | using FlatFile.FixedLength.Attributes.Infrastructure; 10 | 11 | /// 12 | /// Class FlatFileEngineFactoryExtensions. 13 | /// 14 | public static class FlatFileEngineFactoryExtensions 15 | { 16 | /// 17 | /// Gets the engine. 18 | /// 19 | /// The type of the t entity. 20 | /// The engine factory. 21 | /// The handle entry read error. 22 | /// IFlatFileEngine. 23 | public static IFlatFileEngine GetEngine( 24 | this IFlatFileEngineFactory, IFixedFieldSettingsContainer> engineFactory, 25 | Func handleEntryReadError = null) 26 | where TEntity : class, new() 27 | { 28 | var descriptorProvider = new FixedLayoutDescriptorProvider(); 29 | 30 | var descriptor = descriptorProvider.GetDescriptor(); 31 | 32 | return engineFactory.GetEngine(descriptor, handleEntryReadError); 33 | } 34 | 35 | /// 36 | /// Gets the engine. 37 | /// 38 | /// The engine factory. 39 | /// The record types. 40 | /// The type selector function. 41 | /// The handle entry read error. 42 | /// IFlatFileMultiEngine. 43 | public static IFlatFileMultiEngine GetEngine( 44 | this FixedLengthFileEngineFactory engineFactory, 45 | IEnumerable recordTypes, 46 | Func typeSelectorFunc, 47 | Func handleEntryReadError = null) 48 | { 49 | var descriptorProvider = new FixedLayoutDescriptorProvider(); 50 | var descriptors = recordTypes.Select(type => descriptorProvider.GetDescriptor(type)).ToList(); 51 | return engineFactory.GetEngine(descriptors, typeSelectorFunc, handleEntryReadError); 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /src/FlatFile.FixedLength.Attributes/Infrastructure/FixedLayoutDescriptorProvider.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.FixedLength.Attributes.Infrastructure 2 | { 3 | using System; 4 | using System.Linq; 5 | using FlatFile.Core; 6 | using FlatFile.Core.Attributes.Extensions; 7 | using FlatFile.Core.Attributes.Infrastructure; 8 | using FlatFile.Core.Base; 9 | 10 | public class FixedLayoutDescriptorProvider : ILayoutDescriptorProvider> 11 | { 12 | public ILayoutDescriptor GetDescriptor() 13 | { 14 | return GetDescriptor(typeof(T)); 15 | } 16 | 17 | public ILayoutDescriptor GetDescriptor(Type t) 18 | { 19 | var container = new FieldsContainer(); 20 | 21 | var fileMappingType = t; 22 | 23 | var fileAttribute = fileMappingType.GetAttribute(); 24 | 25 | if (fileAttribute == null) 26 | { 27 | throw new NotSupportedException(string.Format("Mapping type {0} should be marked with {1} attribute", 28 | fileMappingType.Name, 29 | typeof(FixedLengthFileAttribute).Name)); 30 | } 31 | 32 | var properties = fileMappingType.GetTypeDescription(); 33 | 34 | foreach (var p in properties) 35 | { 36 | var attribute = p.Attributes.FirstOrDefault() as IFixedFieldSettings; 37 | 38 | if (attribute != null) 39 | { 40 | container.AddOrUpdate(p.Property, new FixedFieldSettings(p.Property, attribute)); 41 | } 42 | } 43 | 44 | var descriptor = new LayoutDescriptorBase(container, t) {HasHeader = false}; 45 | 46 | return descriptor; 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /src/FlatFile.FixedLength.Attributes/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("FlatFile.FixedLength.Attributes")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("FlatFile.FixedLength.Attributes")] 13 | [assembly: AssemblyCopyright("Copyright © 2014")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("f41f342b-68ca-4b29-b095-a8bbdae59ba0")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/FlatFile.FixedLength/FixedFieldSettings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace FlatFile.FixedLength 4 | { 5 | using System.Reflection; 6 | using FlatFile.Core.Base; 7 | 8 | public interface IFixedFieldSettings : IFieldSettings 9 | { 10 | int Length { get; } 11 | bool PadLeft { get; } 12 | char PaddingChar { get; } 13 | bool TruncateIfExceedFieldLength { get; } 14 | Func StringNormalizer { get; } 15 | } 16 | 17 | public interface IFixedFieldSettingsContainer : IFixedFieldSettings, IFieldSettingsContainer 18 | { 19 | } 20 | 21 | public class FixedFieldSettings : FieldSettingsBase, IFixedFieldSettingsContainer 22 | { 23 | public FixedFieldSettings(PropertyInfo propertyInfo) : base(propertyInfo) 24 | { 25 | } 26 | 27 | public FixedFieldSettings(IFixedFieldSettings settings) 28 | : base(settings) 29 | { 30 | Length = settings.Length; 31 | PadLeft = settings.PadLeft; 32 | PaddingChar = settings.PaddingChar; 33 | TypeConverter = settings.TypeConverter; 34 | TruncateIfExceedFieldLength = settings.TruncateIfExceedFieldLength; 35 | StringNormalizer = settings.StringNormalizer; 36 | } 37 | 38 | public FixedFieldSettings(PropertyInfo propertyInfo, IFixedFieldSettings settings) 39 | : this(settings) 40 | { 41 | PropertyInfo = propertyInfo; 42 | } 43 | 44 | public int Length { get; set; } 45 | public bool PadLeft { get; set; } 46 | public char PaddingChar { get; set; } 47 | public bool TruncateIfExceedFieldLength { get; set; } 48 | public Func StringNormalizer { get; set; } 49 | } 50 | } -------------------------------------------------------------------------------- /src/FlatFile.FixedLength/IDetailRecord.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.FixedLength 2 | { 3 | /// 4 | /// Interface IDetailRecord 5 | /// 6 | /// 7 | /// Used to decorate a record as a detail type in a master/detail relationship 8 | /// 9 | public interface IDetailRecord 10 | { 11 | } 12 | } -------------------------------------------------------------------------------- /src/FlatFile.FixedLength/IFixedFieldSettingsConstructor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace FlatFile.FixedLength 4 | { 5 | using FlatFile.Core; 6 | 7 | public interface IFixedFieldSettingsConstructor : 8 | IFieldSettingsConstructor 9 | { 10 | int Length { get; } 11 | char PaddingChar { get; } 12 | bool PadLeft { get; } 13 | 14 | IFixedFieldSettingsConstructor WithLength(int length); 15 | 16 | IFixedFieldSettingsConstructor WithLeftPadding(char paddingChar); 17 | 18 | IFixedFieldSettingsConstructor WithRightPadding(char paddingChar); 19 | 20 | IFixedFieldSettingsConstructor TruncateFieldContentIfExceedLength(); 21 | 22 | IFixedFieldSettingsConstructor WithStringNormalizer(Func stringNormalizer); 23 | } 24 | } -------------------------------------------------------------------------------- /src/FlatFile.FixedLength/IFixedLayout.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.FixedLength 2 | { 3 | using FlatFile.Core; 4 | 5 | public interface IFixedLayout : 6 | ILayout> 7 | { 8 | } 9 | } -------------------------------------------------------------------------------- /src/FlatFile.FixedLength/IFixedLengthLineBuilder.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.FixedLength 2 | { 3 | using FlatFile.Core; 4 | 5 | public interface IFixedLengthLineBuilder : ILineBulder 6 | { 7 | } 8 | } -------------------------------------------------------------------------------- /src/FlatFile.FixedLength/IFixedLengthLineBuilderFactory.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.FixedLength 2 | { 3 | using FlatFile.Core; 4 | 5 | public interface IFixedLengthLineBuilderFactory : 6 | ILineBuilderFactory, IFixedFieldSettingsContainer> 7 | { 8 | } 9 | } -------------------------------------------------------------------------------- /src/FlatFile.FixedLength/IFixedLengthLineParser.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.FixedLength 2 | { 3 | using FlatFile.Core; 4 | 5 | public interface IFixedLengthLineParser : ILineParser 6 | { 7 | } 8 | } -------------------------------------------------------------------------------- /src/FlatFile.FixedLength/IFixedLengthLineParserFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using FlatFile.Core.Base; 3 | 4 | namespace FlatFile.FixedLength 5 | { 6 | using FlatFile.Core; 7 | 8 | /// 9 | /// Interface IFixedLengthLineParserFactory 10 | /// 11 | public interface IFixedLengthLineParserFactory : 12 | ILineParserFactory, IFixedFieldSettingsContainer> 13 | { 14 | /// 15 | /// Registers the line parser for lines matching . 16 | /// 17 | /// The type of the t parser. 18 | /// The target record type. 19 | /// 20 | void RegisterLineParser(Type targetType) where TParser : IFixedLengthLineParser; 21 | 22 | /// 23 | /// Registers the line parser for lines matching . 24 | /// 25 | /// The type of the t parser. 26 | /// The target layout. 27 | /// 28 | void RegisterLineParser(ILayoutDescriptor targetLayout) where TParser : IFixedLengthLineParser; 29 | } 30 | } -------------------------------------------------------------------------------- /src/FlatFile.FixedLength/IMasterRecord.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using FlatFile.Core; 3 | 4 | namespace FlatFile.FixedLength 5 | { 6 | /// 7 | /// Interface IMasterRecord 8 | /// 9 | /// 10 | /// Used to decorate a record as a master type in a master/detail relationship. 11 | /// 12 | public interface IMasterRecord 13 | { 14 | /// 15 | /// Gets the detail records. 16 | /// 17 | /// The detail records. 18 | /// 19 | /// This list will be populated with related detail records when parsing a fixed length file with the 20 | /// 21 | IList DetailRecords { get; } 22 | } 23 | } -------------------------------------------------------------------------------- /src/FlatFile.FixedLength/Implementation/FixedFieldSettingsConstructor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace FlatFile.FixedLength.Implementation 4 | { 5 | using System.Reflection; 6 | using FlatFile.Core; 7 | using FlatFile.Core.Extensions; 8 | 9 | public class FixedFieldSettingsConstructor : FixedFieldSettings, 10 | IFixedFieldSettingsConstructor 11 | { 12 | public FixedFieldSettingsConstructor(PropertyInfo propertyInfo) : base(propertyInfo) 13 | { 14 | } 15 | 16 | public IFixedFieldSettingsConstructor TruncateFieldContentIfExceedLength() 17 | { 18 | TruncateIfExceedFieldLength = true; 19 | return this; 20 | } 21 | 22 | public IFixedFieldSettingsConstructor WithStringNormalizer(Func stringNormalizer) 23 | { 24 | StringNormalizer = stringNormalizer; 25 | return this; 26 | } 27 | 28 | public IFixedFieldSettingsConstructor WithLength(int length) 29 | { 30 | Length = length; 31 | return this; 32 | } 33 | 34 | public IFixedFieldSettingsConstructor WithLeftPadding(char paddingChar) 35 | { 36 | PaddingChar = paddingChar; 37 | PadLeft = true; 38 | return this; 39 | } 40 | 41 | public IFixedFieldSettingsConstructor WithRightPadding(char paddingChar) 42 | { 43 | PaddingChar = paddingChar; 44 | PadLeft = false; 45 | return this; 46 | } 47 | 48 | public IFixedFieldSettingsConstructor AllowNull(string nullValue) 49 | { 50 | IsNullable = true; 51 | NullValue = nullValue; 52 | return this; 53 | } 54 | 55 | public IFixedFieldSettingsConstructor WithTypeConverter() where TConverter : ITypeConverter 56 | { 57 | this.TypeConverter = ReflectionHelper.CreateInstance(true); 58 | return this; 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /src/FlatFile.FixedLength/Implementation/FixedFieldSettingsFactory.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.FixedLength.Implementation 2 | { 3 | using System.Reflection; 4 | using FlatFile.Core; 5 | 6 | public class FixedFieldSettingsFactory : IFieldSettingsFactory 7 | { 8 | public IFixedFieldSettingsConstructor CreateFieldSettings(PropertyInfo property) 9 | { 10 | return new FixedFieldSettingsConstructor(property); 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /src/FlatFile.FixedLength/Implementation/FixedLayout.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.FixedLength.Implementation 2 | { 3 | using System; 4 | using System.Linq.Expressions; 5 | using FlatFile.Core; 6 | using FlatFile.Core.Base; 7 | 8 | public class FixedLayout : 9 | LayoutBase>, 10 | IFixedLayout 11 | { 12 | public FixedLayout() 13 | : this( 14 | new FixedFieldSettingsFactory(), 15 | new FieldsContainer()) 16 | { 17 | } 18 | 19 | public FixedLayout( 20 | IFieldSettingsFactory fieldSettingsFactory, 21 | IFieldsContainer fieldsContainer) 22 | : base(fieldSettingsFactory, fieldsContainer) 23 | { 24 | } 25 | 26 | public override IFixedLayout WithMember( 27 | Expression> expression, 28 | Action settings = null) 29 | { 30 | ProcessProperty(expression, settings); 31 | 32 | return this; 33 | } 34 | 35 | public override IFixedLayout WithHeader() 36 | { 37 | HasHeader = true; 38 | 39 | return this; 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /src/FlatFile.FixedLength/Implementation/FixedLengthFileEngine.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.FixedLength.Implementation 2 | { 3 | using System; 4 | using FlatFile.Core; 5 | using FlatFile.Core.Base; 6 | 7 | /// 8 | /// Class FixedLengthFileEngine. 9 | /// 10 | public class FixedLengthFileEngine : FlatFileEngine> 11 | { 12 | /// 13 | /// The line builder factory 14 | /// 15 | private readonly IFixedLengthLineBuilderFactory lineBuilderFactory; 16 | /// 17 | /// The line parser factory 18 | /// 19 | private readonly IFixedLengthLineParserFactory lineParserFactory; 20 | /// 21 | /// The layout descriptor 22 | /// 23 | private readonly ILayoutDescriptor layoutDescriptor; 24 | 25 | /// 26 | /// Initializes a new instance of the class. 27 | /// 28 | /// The layout descriptor. 29 | /// The line builder factory. 30 | /// The line parser factory. 31 | /// The handle entry read error. 32 | internal FixedLengthFileEngine( 33 | ILayoutDescriptor layoutDescriptor, 34 | IFixedLengthLineBuilderFactory lineBuilderFactory, 35 | IFixedLengthLineParserFactory lineParserFactory, 36 | Func handleEntryReadError = null) : base(handleEntryReadError) 37 | { 38 | this.lineBuilderFactory = lineBuilderFactory; 39 | this.lineParserFactory = lineParserFactory; 40 | this.layoutDescriptor = layoutDescriptor; 41 | } 42 | 43 | /// 44 | /// Gets the line builder. 45 | /// 46 | /// The line builder. 47 | protected override ILineBulder LineBuilder 48 | { 49 | get { return lineBuilderFactory.GetBuilder(LayoutDescriptor); } 50 | } 51 | 52 | /// 53 | /// Gets the line parser. 54 | /// 55 | /// The line parser. 56 | protected override ILineParser LineParser 57 | { 58 | get { return lineParserFactory.GetParser(LayoutDescriptor); } 59 | } 60 | 61 | /// 62 | /// Gets the layout descriptor. 63 | /// 64 | /// The layout descriptor. 65 | protected override ILayoutDescriptor LayoutDescriptor 66 | { 67 | get { return layoutDescriptor; } 68 | } 69 | } 70 | } -------------------------------------------------------------------------------- /src/FlatFile.FixedLength/Implementation/FixedLengthFileEngineFactory.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using FlatFile.Core.Base; 3 | 4 | namespace FlatFile.FixedLength.Implementation 5 | { 6 | using System; 7 | using FlatFile.Core; 8 | 9 | /// 10 | /// Class FixedLengthFileEngineFactory. 11 | /// 12 | public class FixedLengthFileEngineFactory : IFlatFileEngineFactory, IFixedFieldSettingsContainer> 13 | { 14 | readonly FixedLengthLineParserFactory lineParserFactory = new FixedLengthLineParserFactory(); 15 | 16 | /// 17 | /// Registers the line parser for lines matching . 18 | /// 19 | /// The type of the t parser. 20 | /// The target record type. 21 | /// 22 | public void RegisterLineParser(Type targetType) where TParser : IFixedLengthLineParser 23 | { 24 | lineParserFactory.RegisterLineParser(targetType); 25 | } 26 | 27 | /// 28 | /// Registers the line parser for lines matching . 29 | /// 30 | /// The type of the t parser. 31 | /// The target layout. 32 | /// 33 | public void RegisterLineParser(ILayoutDescriptor targetLayout) where TParser : IFixedLengthLineParser 34 | { 35 | lineParserFactory.RegisterLineParser(targetLayout); 36 | } 37 | 38 | /// 39 | /// Gets the . 40 | /// 41 | /// The descriptor. 42 | /// The handle entry read error func. 43 | /// IFlatFileEngine. 44 | public IFlatFileEngine GetEngine( 45 | ILayoutDescriptor descriptor, 46 | Func handleEntryReadError = null) 47 | { 48 | return new FixedLengthFileEngine( 49 | descriptor, 50 | new FixedLengthLineBuilderFactory(), 51 | lineParserFactory, 52 | handleEntryReadError); 53 | } 54 | 55 | /// 56 | /// Gets the . 57 | /// 58 | /// The layout descriptors. 59 | /// The type selector function. 60 | /// The handle entry read error func. 61 | /// IFlatFileMultiEngine. 62 | public IFlatFileMultiEngine GetEngine( 63 | IEnumerable> layoutDescriptors, 64 | Func typeSelectorFunc, 65 | Func handleEntryReadError = null) 66 | { 67 | return new FixedLengthFileMultiEngine( 68 | layoutDescriptors, 69 | typeSelectorFunc, 70 | new FixedLengthLineBuilderFactory(), 71 | lineParserFactory, 72 | handleEntryReadError); 73 | } 74 | } 75 | } -------------------------------------------------------------------------------- /src/FlatFile.FixedLength/Implementation/FixedLengthLineBuilder.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.FixedLength.Implementation 2 | { 3 | using System.Linq; 4 | using FlatFile.Core; 5 | using FlatFile.Core.Base; 6 | 7 | public class FixedLengthLineBuilder : 8 | LineBulderBase, IFixedFieldSettingsContainer>, 9 | IFixedLengthLineBuilder 10 | { 11 | public FixedLengthLineBuilder(ILayoutDescriptor descriptor) 12 | : base(descriptor) 13 | { 14 | } 15 | 16 | public override string BuildLine(T entry) 17 | { 18 | string line = Descriptor.Fields.Aggregate(string.Empty, 19 | (current, field) => current + GetStringValueFromField(field, field.PropertyInfo.GetValue(entry, null))); 20 | return line; 21 | } 22 | 23 | protected override string TransformFieldValue(IFixedFieldSettingsContainer field, string lineValue) 24 | { 25 | if (field.StringNormalizer != null) 26 | { 27 | lineValue = field.StringNormalizer(lineValue); 28 | } 29 | 30 | if (lineValue.Length >= field.Length) 31 | { 32 | return field.TruncateIfExceedFieldLength ? lineValue.Substring(0, field.Length) : lineValue; 33 | } 34 | 35 | lineValue = field.PadLeft 36 | ? lineValue.PadLeft(field.Length, field.PaddingChar) 37 | : lineValue.PadRight(field.Length, field.PaddingChar); 38 | 39 | return lineValue; 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /src/FlatFile.FixedLength/Implementation/FixedLengthLineBuilderFactory.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.FixedLength.Implementation 2 | { 3 | using FlatFile.Core; 4 | 5 | public class FixedLengthLineBuilderFactory : IFixedLengthLineBuilderFactory 6 | { 7 | public IFixedLengthLineBuilder GetBuilder(ILayoutDescriptor descriptor) 8 | { 9 | return new FixedLengthLineBuilder(descriptor); 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /src/FlatFile.FixedLength/Implementation/FixedLengthLineParser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace FlatFile.FixedLength.Implementation 4 | { 5 | using FlatFile.Core; 6 | using FlatFile.Core.Base; 7 | 8 | public class FixedLengthLineParser : 9 | LineParserBase, IFixedFieldSettingsContainer>, 10 | IFixedLengthLineParser 11 | { 12 | public FixedLengthLineParser(ILayoutDescriptor layout) 13 | : base(layout) 14 | { 15 | } 16 | 17 | public override TEntity ParseLine(string line, TEntity entity) 18 | { 19 | int linePosition = 0; 20 | foreach (var field in Layout.Fields) 21 | { 22 | string fieldValueFromLine = GetValueFromLine(line, linePosition, field); 23 | object convertedFieldValue = GetFieldValueFromString(field, fieldValueFromLine); 24 | field.PropertyInfo.SetValue(entity, convertedFieldValue, null); 25 | linePosition += field.Length; 26 | } 27 | return entity; 28 | } 29 | 30 | private static string GetValueFromLine(string line, int linePosition, IFixedFieldSettingsContainer field) 31 | { 32 | if (linePosition + field.Length > line.Length) 33 | { 34 | if ((linePosition + field.Length) - line.Length != field.Length && linePosition <= line.Length) 35 | { 36 | return line.Substring(linePosition); 37 | } 38 | 39 | if (field.IsNullable) 40 | { 41 | return field.NullValue; 42 | } 43 | 44 | throw new IndexOutOfRangeException( 45 | string.Format("The field at {0} with a length of {1} cannot be found on the line because the line is too short. " + 46 | "Setting a NullValue for this field will allow the line to be parsed and this field to be null.", field.Index, field.Length)); 47 | } 48 | 49 | return line.Substring(linePosition, field.Length); 50 | } 51 | 52 | protected override string TransformStringValue(IFixedFieldSettingsContainer fieldSettingsBuilder, string memberValue) 53 | { 54 | memberValue = fieldSettingsBuilder.PadLeft 55 | ? memberValue.TrimStart(new[] {fieldSettingsBuilder.PaddingChar}) 56 | : memberValue.TrimEnd(new[] {fieldSettingsBuilder.PaddingChar}); 57 | 58 | return memberValue; 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /src/FlatFile.FixedLength/Implementation/FixedLengthLineParserFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using FlatFile.Core.Base; 5 | using FlatFile.Core.Extensions; 6 | 7 | namespace FlatFile.FixedLength.Implementation 8 | { 9 | using Core; 10 | 11 | /// 12 | /// Class FixedLengthLineParserFactory. 13 | /// 14 | public class FixedLengthLineParserFactory : IFixedLengthLineParserFactory 15 | { 16 | readonly Dictionary lineParserRegistry; 17 | 18 | /// 19 | /// Initializes a new instance of the class. 20 | /// 21 | public FixedLengthLineParserFactory() { lineParserRegistry = new Dictionary(); } 22 | 23 | /// 24 | /// Initializes a new instance of the class. 25 | /// 26 | /// The line parser registry. 27 | public FixedLengthLineParserFactory(IDictionary lineParserRegistry) { this.lineParserRegistry = new Dictionary(lineParserRegistry); } 28 | 29 | /// 30 | /// Initializes a new instance of the class. 31 | /// 32 | /// The line parser registry. 33 | public FixedLengthLineParserFactory(IDictionary> lineParserRegistry) 34 | { 35 | this.lineParserRegistry = lineParserRegistry.ToDictionary(descriptor => descriptor.Key, descriptor => descriptor.Value.TargetType); 36 | } 37 | 38 | /// 39 | /// Gets the parser. 40 | /// 41 | /// The descriptor. 42 | /// IFixedLengthLineParser. 43 | public IFixedLengthLineParser GetParser(ILayoutDescriptor descriptor) 44 | { 45 | if (descriptor == null) throw new ArgumentNullException("descriptor"); 46 | 47 | return descriptor.TargetType != null && lineParserRegistry.ContainsKey(descriptor.TargetType) 48 | ? (IFixedLengthLineParser) ReflectionHelper.CreateInstance(lineParserRegistry[descriptor.TargetType], true, descriptor) 49 | : new FixedLengthLineParser(descriptor); 50 | } 51 | 52 | /// 53 | /// Registers the line parser for lines matching . 54 | /// 55 | /// The type of the t parser. 56 | /// The target record type. 57 | public void RegisterLineParser(Type targetType) where TParser : IFixedLengthLineParser 58 | { 59 | lineParserRegistry[targetType] = typeof (TParser); 60 | } 61 | 62 | /// 63 | /// Registers the line parser for lines matching . 64 | /// 65 | /// The type of the t parser. 66 | /// The target layout. 67 | public void RegisterLineParser(ILayoutDescriptor targetLayout) where TParser : IFixedLengthLineParser 68 | { 69 | lineParserRegistry[targetLayout.TargetType] = typeof (TParser); 70 | } 71 | } 72 | } -------------------------------------------------------------------------------- /src/FlatFile.FixedLength/Padding.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.FixedLength 2 | { 3 | public enum Padding 4 | { 5 | Left, 6 | Right 7 | } 8 | } -------------------------------------------------------------------------------- /src/FlatFile.FixedLength/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | 9 | [assembly: AssemblyTitle("FlatFile.FixedLength")] 10 | [assembly: AssemblyDescription("")] 11 | [assembly: AssemblyConfiguration("")] 12 | [assembly: AssemblyCompany("EPAM Systems")] 13 | [assembly: AssemblyProduct("FlatFile.FixedLength")] 14 | [assembly: AssemblyCopyright("Copyright © EPAM Systems 2014")] 15 | [assembly: AssemblyTrademark("")] 16 | [assembly: AssemblyCulture("")] 17 | 18 | // Setting ComVisible to false makes the types in this assembly not visible 19 | // to COM components. If you need to access a type in this assembly from 20 | // COM, set the ComVisible attribute to true on that type. 21 | 22 | [assembly: ComVisible(false)] 23 | 24 | // The following GUID is for the ID of the typelib if this project is exposed to COM 25 | 26 | [assembly: Guid("4f911ba4-3051-4146-a688-e11653eebc33")] 27 | 28 | // Version information for an assembly consists of the following four values: 29 | // 30 | // Major Version 31 | // Minor Version 32 | // Build Number 33 | // Revision 34 | // 35 | // You can specify all the values or you can default the Build and Revision Numbers 36 | // by using the '*' as shown below: 37 | // [assembly: AssemblyVersion("1.0.*")] 38 | 39 | [assembly: AssemblyVersion("1.0.0.0")] 40 | [assembly: AssemblyFileVersion("1.0.0.0")] 41 | [assembly: InternalsVisibleTo("FlatFile.Tests")] -------------------------------------------------------------------------------- /src/FlatFile.Tests/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 |
5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/FlatFile.Tests/Base/Entities/TestObject.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Tests.Base.Entities 2 | { 3 | using System; 4 | using FlatFile.Delimited.Attributes; 5 | using FlatFile.FixedLength; 6 | using FlatFile.FixedLength.Attributes; 7 | 8 | [FixedLengthFile] 9 | [DelimitedFile(Delimiter = ";", Quotes = "\"")] 10 | public class TestObject : IEquatable 11 | { 12 | [FixedLengthField(1, 5, PaddingChar = '0')] 13 | [DelimitedField(1)] 14 | public int Id { get; set; } 15 | 16 | [FixedLengthField(2, 25, PaddingChar = ' ', Padding = Padding.Right)] 17 | [DelimitedField(2)] 18 | public string Description { get; set; } 19 | 20 | [FixedLengthField(2, 5, PaddingChar = '0', NullValue = "=Null")] 21 | [DelimitedField(3, NullValue = "=Null")] 22 | public int? NullableInt { get; set; } 23 | 24 | public int GetHashCode(TestObject obj) 25 | { 26 | var idHash = Id.GetHashCode(); 27 | var descriptionHash = Object.ReferenceEquals(Description, null) ? 0 : Description.GetHashCode(); 28 | var nullableIntHash = !NullableInt.HasValue ? 0 : NullableInt.Value.GetHashCode(); 29 | return idHash ^ descriptionHash ^ nullableIntHash; 30 | } 31 | 32 | public bool Equals(TestObject other) 33 | { 34 | if (ReferenceEquals(other, null)) 35 | { 36 | return false; 37 | } 38 | 39 | if (ReferenceEquals(other, this)) 40 | { 41 | return true; 42 | } 43 | 44 | return Equals(Id, other.Id) && Equals(Description, other.Description) && 45 | Equals(NullableInt, other.NullableInt); 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /src/FlatFile.Tests/Base/IntegrationTests.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Tests.Base 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Text; 8 | using FlatFile.Core; 9 | using FlatFile.Core.Base; 10 | using FlatFile.Tests.Base.Entities; 11 | using FluentAssertions; 12 | using Xunit; 13 | 14 | public abstract class IntegrationTests 15 | where TLayout : ILayout 16 | where TFieldSettings : IFieldSettingsContainer 17 | where TConstructor : IFieldSettingsConstructor 18 | { 19 | protected abstract TLayout Layout { get; } 20 | 21 | protected IList Objects { get; set; } 22 | 23 | protected abstract IFlatFileEngine Engine { get; } 24 | 25 | public abstract string TestSource { get; } 26 | 27 | protected IntegrationTests() 28 | { 29 | Objects = new List(); 30 | 31 | for (int i = 1; i <= 10; i++) 32 | { 33 | Objects.Add(new TestObject 34 | { 35 | Id = i, 36 | Description = "Description " + i, 37 | NullableInt = i%5 == 0 ? null : (int?) 3 38 | }); 39 | } 40 | } 41 | 42 | [Fact] 43 | public virtual void CoundOfTheObjectsAfterWriteReadShouldBeTheSame() 44 | { 45 | InvokeWriteTest((engine, stream) => 46 | { 47 | var objectsAfterRead = engine.Read(stream).ToArray(); 48 | 49 | objectsAfterRead.Should().HaveCount(Objects.Count); 50 | 51 | }); 52 | } 53 | 54 | [Fact] 55 | public virtual void AllDeclaredPropertiesOfTheObjectsAfterWriteReadShouldBeTheSame() 56 | { 57 | InvokeWriteTest((engine, stream) => 58 | { 59 | var objectsAfterRead = engine.Read(stream).ToList(); 60 | 61 | objectsAfterRead.ShouldAllBeEquivalentTo(Objects, options => options.IncludingAllDeclaredProperties()); 62 | 63 | }); 64 | } 65 | 66 | [Fact] 67 | public void AllDeclaredPropertiesOfTheObjectsAfterReadFromSourceShouldBeTheSame() 68 | { 69 | InvokeReadbasedTest((engine, stream) => 70 | { 71 | var objectsAfterRead = engine.Read(stream).ToList(); 72 | 73 | objectsAfterRead.ShouldAllBeEquivalentTo(Objects, options => options.IncludingAllDeclaredProperties()); 74 | 75 | }, TestSource); 76 | } 77 | 78 | protected virtual void InvokeWriteTest(Action action) 79 | { 80 | using (var memory = new MemoryStream()) 81 | { 82 | Engine.Write(memory, Objects); 83 | 84 | memory.Seek(0, SeekOrigin.Begin); 85 | 86 | action(Engine, memory); 87 | } 88 | } 89 | 90 | protected virtual void InvokeReadbasedTest(Action action, 91 | string textSource) 92 | { 93 | using (var memory = new MemoryStream(Encoding.UTF8.GetBytes(textSource))) 94 | { 95 | action(Engine, memory); 96 | } 97 | } 98 | } 99 | } -------------------------------------------------------------------------------- /src/FlatFile.Tests/Core/FieldsContainerTests.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Tests.Core 2 | { 3 | using System.Linq; 4 | using System.Reflection; 5 | using FlatFile.Core.Base; 6 | using FlatFile.Core.Extensions; 7 | using FlatFile.FixedLength; 8 | using FlatFile.Tests.Base.Entities; 9 | using FluentAssertions; 10 | using Xunit; 11 | 12 | public class FieldsContainerTests 13 | { 14 | private readonly FieldsContainer _fieldsContainer; 15 | private readonly TestObject _testObject; 16 | private readonly PropertyInfo _propertyInfo; 17 | private readonly FixedFieldSettings _fieldSettings; 18 | private readonly PropertyInfo[] _properties; 19 | 20 | public FieldsContainerTests() 21 | { 22 | _fieldsContainer = new AutoOrderedFieldsContainer(); 23 | _testObject = new TestObject(); 24 | 25 | _properties = new[] 26 | { 27 | ExpressionExtensions.GetPropertyInfo(() => _testObject.Id), 28 | ExpressionExtensions.GetPropertyInfo(() => _testObject.Description), 29 | ExpressionExtensions.GetPropertyInfo(() => _testObject.NullableInt) 30 | }; 31 | 32 | _propertyInfo = ExpressionExtensions.GetPropertyInfo(() => _testObject.Description); 33 | 34 | _fieldSettings = new FixedFieldSettings(_propertyInfo); 35 | } 36 | 37 | [Fact] 38 | public void OrderedFieldsShouldContainsOneItemAfterAdd() 39 | { 40 | _fieldsContainer.AddOrUpdate(_propertyInfo, _fieldSettings); 41 | 42 | _fieldsContainer.OrderedFields.Should().HaveCount(1); 43 | } 44 | 45 | [Fact] 46 | public void AddOrUpdateShouldAssingRightId() 47 | { 48 | _fieldsContainer.AddOrUpdate(_propertyInfo, _fieldSettings); 49 | 50 | _fieldsContainer.OrderedFields.First().Index.Should().Be(0); 51 | } 52 | 53 | [Fact] 54 | public void OrderedFieldsShouldContainsOneItemAfterUpdate() 55 | { 56 | _fieldsContainer.AddOrUpdate(_propertyInfo, _fieldSettings); 57 | 58 | _fieldSettings.IsNullable = true; 59 | 60 | _fieldsContainer.AddOrUpdate(_propertyInfo, _fieldSettings); 61 | 62 | _fieldsContainer.OrderedFields.Should().HaveCount(1); 63 | } 64 | 65 | [Fact] 66 | public void AllAddedPropertyShouldBeInTheOrderedFields() 67 | { 68 | foreach (var property in _properties) 69 | { 70 | _fieldsContainer.AddOrUpdate(property, new FixedFieldSettings(property)); 71 | } 72 | 73 | _fieldsContainer.OrderedFields.Should().HaveCount(_properties.Length); 74 | } 75 | 76 | [Fact] 77 | public void OrderedFieldsShouldContainsOrderedProperties() 78 | { 79 | foreach (var property in _properties) 80 | { 81 | _fieldsContainer.AddOrUpdate(property, new FixedFieldSettings(property)); 82 | } 83 | 84 | int id = 0; 85 | 86 | foreach (var field in _fieldsContainer.OrderedFields) 87 | { 88 | field.Index.Should().Be(id++); 89 | } 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/FlatFile.Tests/Delimited/DelimitedAttributeMappingIntegrationTests.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Linq; 3 | using System.Reflection; 4 | using FakeItEasy; 5 | using FlatFile.Core.Base; 6 | using FlatFile.Core; 7 | using FlatFile.Delimited; 8 | using FlatFile.Delimited.Attributes; 9 | using FlatFile.Delimited.Implementation; 10 | using FlatFile.Tests.Base.Entities; 11 | using Xunit; 12 | 13 | namespace FlatFile.Tests.Delimited 14 | { 15 | public class DelimitedAttributeMappingIntegrationTests : DelimitedIntegrationTests 16 | { 17 | private readonly IFlatFileEngineFactory _fileEngineFactory; 18 | 19 | public DelimitedAttributeMappingIntegrationTests() 20 | { 21 | _fileEngineFactory = new DelimitedFileEngineFactory(); 22 | } 23 | 24 | protected override IFlatFileEngine Engine 25 | { 26 | get { return _fileEngineFactory.GetEngine(); } 27 | } 28 | 29 | class ConverterTestObject 30 | { 31 | public string Foo { get; set; } 32 | } 33 | 34 | [Fact] 35 | public void EngineShouldCallTypeConverterWhenConverterAttributeIsPresent() 36 | { 37 | // a converter to convert "A" to "foo" 38 | var converter = A.Fake(); 39 | A.CallTo(() => converter.ConvertFromString("A")).Returns("foo"); 40 | A.CallTo(() => converter.CanConvertFrom(typeof(string))).Returns(true); 41 | A.CallTo(() => converter.CanConvertTo(typeof(string))).Returns(true); 42 | 43 | // an attribute to assign the property 44 | var attribute = A.Fake(); 45 | A.CallTo(() => attribute.Index).Returns(1); 46 | A.CallTo(() => attribute.TypeConverter).Returns(converter); 47 | 48 | // the properties of the class 49 | var properties = typeof(ConverterTestObject).GetProperties(BindingFlags.Instance | BindingFlags.Public).ToDictionary(info => info.Name); 50 | 51 | // assign the attribute to the Foo property 52 | var container = new FieldsContainer(); 53 | container.AddOrUpdate(properties["Foo"], new DelimitedFieldSettings(properties["Foo"], attribute)); 54 | 55 | var layout = new DelimitedLayout(new DelimitedFieldSettingsFactory(), container); 56 | var engine = _fileEngineFactory.GetEngine(layout); 57 | 58 | // write "A" to the stream and verify it is converted to "foo" 59 | using (var stream = new MemoryStream()) 60 | using (var writer = new StreamWriter(stream)) 61 | { 62 | writer.WriteLine("A"); 63 | writer.Flush(); 64 | stream.Seek(0, SeekOrigin.Begin); 65 | // Capture first result to force enumerable to be iterated 66 | var result = engine.Read(stream).FirstOrDefault(); 67 | Assert.Equal("foo", result.Foo); 68 | } 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /src/FlatFile.Tests/Delimited/DelimitedIntegrationTests.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Tests.Delimited 2 | { 3 | using FlatFile.Core; 4 | using FlatFile.Delimited; 5 | using FlatFile.Delimited.Implementation; 6 | using FlatFile.Tests.Base; 7 | using FlatFile.Tests.Base.Entities; 8 | 9 | public class DelimitedIntegrationTests : 10 | IntegrationTests> 11 | { 12 | private readonly IDelimitedLayout _layout; 13 | 14 | private readonly IFlatFileEngine _engine; 15 | 16 | private const string _testSource = "\"1\";\"Description 1\";\"3\"\r\n" + 17 | "\"2\";\"Description 2\";\"3\"\r\n" + 18 | "\"3\";\"Description 3\";\"3\"\r\n" + 19 | "\"4\";\"Description 4\";\"3\"\r\n" + 20 | "\"5\";\"Description 5\";=Null\r\n" + 21 | "\"6\";\"Description 6\";\"3\"\r\n" + 22 | "\"7\";\"Description 7\";\"3\"\r\n" + 23 | "\"8\";\"Description 8\";\"3\"\r\n" + 24 | "\"9\";\"Description 9\";\"3\"\r\n" + 25 | "\"10\";\"Description 10\";=Null"; 26 | 27 | public DelimitedIntegrationTests() 28 | { 29 | _layout = new DelimitedLayout() 30 | .WithDelimiter(";") 31 | .WithQuote("\"") 32 | .WithMember(o => o.Id) 33 | .WithMember(o => o.Description) 34 | .WithMember(o => o.NullableInt, set => set.AllowNull("=Null")); 35 | 36 | _engine = new DelimitedFileEngine( 37 | Layout, 38 | new DelimitedLineBuilderFactory(), 39 | new DelimitedLineParserFactory()); 40 | } 41 | 42 | protected override IDelimitedLayout Layout 43 | { 44 | get { return _layout; } 45 | } 46 | 47 | protected override IFlatFileEngine Engine 48 | { 49 | get { return _engine; } 50 | } 51 | 52 | public override string TestSource 53 | { 54 | get { return _testSource; } 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /src/FlatFile.Tests/Delimited/DelimitedLayoutTests.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Tests.Delimited 2 | { 3 | using FlatFile.Delimited; 4 | using FlatFile.Delimited.Implementation; 5 | using FlatFile.Tests.Base.Entities; 6 | using FluentAssertions; 7 | using Xunit; 8 | 9 | public class DelimitedLayoutTests 10 | { 11 | private readonly IDelimitedLayout layout; 12 | 13 | public DelimitedLayoutTests() 14 | { 15 | layout = new DelimitedLayout() 16 | .WithDelimiter(";") 17 | .WithQuote("\"") 18 | .WithMember(o => o.Id) 19 | .WithMember(o => o.Description) 20 | .WithMember(o => o.NullableInt, set => set.AllowNull("=Null")); 21 | } 22 | 23 | [Fact] 24 | public void FieldsCount() 25 | { 26 | layout.Fields.Should().HaveCount(3); 27 | } 28 | 29 | [Fact] 30 | public void WithHeader() 31 | { 32 | layout.WithHeader(); 33 | 34 | layout.HasHeader.Should().BeTrue(); 35 | } 36 | 37 | [Fact] 38 | public void WithoutHeader() 39 | { 40 | layout.HasHeader.Should().BeFalse(); 41 | } 42 | 43 | [Fact] 44 | public void FieldsCountAfterReplacementShouldNotChange() 45 | { 46 | layout.WithMember(o => o.NullableInt, set => set.AllowNull(string.Empty)); 47 | 48 | layout.Fields.Should().HaveCount(3); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/FlatFile.Tests/Delimited/DelimitedMultiEngineTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using FlatFile.Core; 6 | using FlatFile.Delimited; 7 | using FlatFile.Delimited.Attributes; 8 | using FlatFile.Delimited.Implementation; 9 | using FluentAssertions; 10 | using Xunit; 11 | 12 | namespace FlatFile.Tests.Delimited 13 | { 14 | public class DelimitedMultiEngineTests 15 | { 16 | readonly IFlatFileMultiEngine engine; 17 | 18 | const string TestData = 19 | @"S,Test Description,00042 20 | D,20150323,Another Description"; 21 | 22 | [DelimitedFile(Delimiter = ",", HasHeader = false)] 23 | class Record1 24 | { 25 | [DelimitedField(1)] 26 | public char Type { get; set; } 27 | 28 | [DelimitedField(2)] 29 | public string Description { get; set; } 30 | 31 | [DelimitedField(3)] 32 | public int Value { get; set; } 33 | 34 | public Record1() { Type = 'S'; } 35 | 36 | bool Equals(Record1 other) { return Type == other.Type && string.Equals(Description, other.Description) && Value == other.Value; } 37 | 38 | public override int GetHashCode() 39 | { 40 | unchecked 41 | { 42 | var hashCode = Type.GetHashCode(); 43 | hashCode = (hashCode * 397) ^ (Description != null ? Description.GetHashCode() : 0); 44 | hashCode = (hashCode * 397) ^ Value; 45 | return hashCode; 46 | } 47 | } 48 | 49 | public override bool Equals(object obj) 50 | { 51 | if (ReferenceEquals(null, obj)) return false; 52 | if (ReferenceEquals(this, obj)) return true; 53 | return obj.GetType() == GetType() && Equals((Record1)obj); 54 | } 55 | } 56 | 57 | 58 | [DelimitedFile(Delimiter = ",", HasHeader = false)] 59 | class Record2 60 | { 61 | 62 | [DelimitedField(1)] 63 | public char Type { get; set; } 64 | 65 | [DelimitedField(2)] 66 | public string Date { get; set; } 67 | 68 | [DelimitedField(3)] 69 | public string Description { get; set; } 70 | 71 | public Record2() { Type = 'D'; } 72 | 73 | bool Equals(Record2 other) { return Type == other.Type && string.Equals(Date, other.Date) && string.Equals(Description, other.Description); } 74 | 75 | public override int GetHashCode() 76 | { 77 | unchecked 78 | { 79 | var hashCode = Type.GetHashCode(); 80 | hashCode = (hashCode * 397) ^ (Date != null ? Date.GetHashCode() : 0); 81 | hashCode = (hashCode * 397) ^ (Description != null ? Description.GetHashCode() : 0); 82 | return hashCode; 83 | } 84 | } 85 | 86 | public override bool Equals(object obj) 87 | { 88 | if (ReferenceEquals(null, obj)) return false; 89 | if (ReferenceEquals(this, obj)) return true; 90 | return obj.GetType() == GetType() && Equals((Record2)obj); 91 | } 92 | } 93 | 94 | sealed class Record1Layout : DelimitedLayout 95 | { 96 | public Record1Layout() 97 | { 98 | HasHeader = false; 99 | WithMember(x => x.Type, c => c.WithName("Type")) 100 | .WithMember(x => x.Description, c => c.WithName("Description")) 101 | .WithMember(x => x.Value, c => c.WithName("Value")); 102 | } 103 | } 104 | 105 | sealed class Record2Layout : DelimitedLayout 106 | { 107 | public Record2Layout() 108 | { 109 | WithMember(x => x.Type, c => c.WithName("Type")) 110 | .WithMember(x => x.Date, c => c.WithName("Date")) 111 | .WithMember(x => x.Description, c => c.WithName("Description")); 112 | } 113 | } 114 | 115 | public DelimitedMultiEngineTests() 116 | { 117 | 118 | var factory = new DelimitedFileEngineFactory(); 119 | var types = new System.Collections.Generic.List() 120 | { 121 | typeof(Record1), 122 | typeof(Record2) 123 | }; 124 | 125 | engine = factory.GetEngine(types.AsEnumerable(), 126 | s => 127 | { 128 | if (String.IsNullOrEmpty(s) || s.Length < 1) return null; 129 | 130 | switch (s[0]) 131 | { 132 | case 'S': 133 | return typeof(Record1); 134 | case 'D': 135 | return typeof(Record2); 136 | default: 137 | return null; 138 | } 139 | } 140 | ); 141 | } 142 | 143 | [Fact] 144 | public void EngineShouldReadMultipleRecordTypes() 145 | { 146 | using (var stream = GetStringStream(TestData)) 147 | engine.Read(stream); 148 | 149 | var record1Results = engine.GetRecords().ToList(); 150 | var record2Results = engine.GetRecords().ToList(); 151 | 152 | record1Results.Should().HaveCount(1, "because it should read one 'S' record"); 153 | record2Results.Should().HaveCount(1, "because there is one 'D' record"); 154 | 155 | record1Results.First().Should().Be(new Record1 { Description = "Test Description", Value = 42 }); 156 | record2Results.First().Should().Be(new Record2 { Description = "Another Description", Date = "20150323" }); 157 | } 158 | 159 | static Stream GetStringStream(string s) 160 | { 161 | var memoryStream = new MemoryStream(); 162 | var writer = new StreamWriter(memoryStream); 163 | writer.Write(s); 164 | writer.Flush(); 165 | memoryStream.Position = 0; 166 | return memoryStream; 167 | } 168 | } 169 | } -------------------------------------------------------------------------------- /src/FlatFile.Tests/Delimited/DelimitedWithHeaderIntegrationTests.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Tests.Delimited 2 | { 3 | public sealed class DelimitedWithHeaderIntegrationTests : DelimitedIntegrationTests 4 | { 5 | private const string _testSource = "\"Id\";\"Description\";\"NullableInt\"\r\n" + 6 | "\"1\";\"Description 1\";\"3\"\r\n" + 7 | "\"2\";\"Description 2\";\"3\"\r\n" + 8 | "\"3\";\"Description 3\";\"3\"\r\n" + 9 | "\"4\";\"Description 4\";\"3\"\r\n" + 10 | "\"5\";\"Description 5\";=Null\r\n" + 11 | "\"6\";\"Description 6\";\"3\"\r\n" + 12 | "\"7\";\"Description 7\";\"3\"\r\n" + 13 | "\"8\";\"Description 8\";\"3\"\r\n" + 14 | "\"9\";\"Description 9\";\"3\"\r\n" + 15 | "\"10\";\"Description 10\";=Null"; 16 | 17 | public DelimitedWithHeaderIntegrationTests() 18 | { 19 | Layout.WithHeader(); 20 | } 21 | 22 | public override string TestSource 23 | { 24 | get { return _testSource; } 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /src/FlatFile.Tests/FixedLength/FixedLayoutTests.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Tests.FixedLength 2 | { 3 | using FlatFile.FixedLength; 4 | using FlatFile.FixedLength.Implementation; 5 | using FlatFile.Tests.Base.Entities; 6 | using FluentAssertions; 7 | using Xunit; 8 | 9 | public class FixedLayoutTests 10 | { 11 | private readonly IFixedLayout layout; 12 | 13 | public FixedLayoutTests() 14 | { 15 | layout = new FixedLayout() 16 | .WithMember(o => o.Id, set => set.WithLength(5).WithLeftPadding('0')) 17 | .WithMember(o => o.Description, set => set.WithLength(25).WithRightPadding(' ')) 18 | .WithMember(o => o.NullableInt, set => set.WithLength(5).AllowNull("=Null").WithLeftPadding('0')); 19 | } 20 | 21 | [Fact] 22 | public void FieldsCount() 23 | { 24 | layout.Fields.Should().HaveCount(3); 25 | } 26 | 27 | [Fact] 28 | public void FieldsCountAfterReplacementShouldNotChange() 29 | { 30 | layout.WithMember(o => o.NullableInt, set => set.WithLength(5).AllowNull(string.Empty).WithLeftPadding('0')); 31 | 32 | layout.Fields.Should().HaveCount(3); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/FlatFile.Tests/FixedLength/FixedLengthAttributeMappingIntegrationTests.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Linq; 3 | using System.Reflection; 4 | using FakeItEasy; 5 | using FlatFile.Core; 6 | using FlatFile.Core.Base; 7 | using FlatFile.FixedLength; 8 | using FlatFile.FixedLength.Attributes; 9 | using FlatFile.FixedLength.Implementation; 10 | using FlatFile.Tests.Base.Entities; 11 | using Xunit; 12 | 13 | namespace FlatFile.Tests.FixedLength 14 | { 15 | public class FixedLengthAttributeMappingIntegrationTests : FixedLengthIntegrationTests 16 | { 17 | readonly IFlatFileEngineFactory, IFixedFieldSettingsContainer> fileEngineFactory; 18 | 19 | class ConverterTestObject 20 | { 21 | public string Foo { get; set; } 22 | } 23 | 24 | public FixedLengthAttributeMappingIntegrationTests() { fileEngineFactory = new FixedLengthFileEngineFactory(); } 25 | 26 | [Fact] 27 | public void EngineShouldCallTypeConverterWhenConverterAttributeIsPresent() 28 | { 29 | var converter = A.Fake(); 30 | A.CallTo(converter).WithReturnType().Returns("foo"); 31 | A.CallTo(converter).WithReturnType().Returns(true); 32 | 33 | var attribute = A.Fake(); 34 | A.CallTo(() => attribute.Index).Returns(1); 35 | A.CallTo(() => attribute.Length).Returns(1); 36 | A.CallTo(() => attribute.TypeConverter).Returns(converter); 37 | 38 | var properties = typeof (ConverterTestObject).GetProperties(BindingFlags.Instance | BindingFlags.Public).ToDictionary(info => info.Name); 39 | 40 | var container = new FieldsContainer(); 41 | container.AddOrUpdate(properties["Foo"], new FixedFieldSettings(properties["Foo"], attribute)); 42 | 43 | var descriptor = new LayoutDescriptorBase(container) {HasHeader = false}; 44 | 45 | var engine = fileEngineFactory.GetEngine(descriptor); 46 | 47 | using (var stream = new MemoryStream()) 48 | using (var writer = new StreamWriter(stream)) 49 | { 50 | writer.WriteLine("A"); 51 | writer.Flush(); 52 | stream.Seek(0, SeekOrigin.Begin); 53 | // Capture first result to force enumerable to be iterated 54 | var result = engine.Read(stream).FirstOrDefault(); 55 | } 56 | 57 | A.CallTo(converter).WithReturnType().MustHaveHappened(); 58 | } 59 | 60 | protected override IFlatFileEngine Engine { get { return fileEngineFactory.GetEngine(); } } 61 | } 62 | } -------------------------------------------------------------------------------- /src/FlatFile.Tests/FixedLength/FixedLengthIntegrationTests.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Tests.FixedLength 2 | { 3 | using FlatFile.Core; 4 | using FlatFile.FixedLength; 5 | using FlatFile.FixedLength.Implementation; 6 | using FlatFile.Tests.Base; 7 | using FlatFile.Tests.Base.Entities; 8 | 9 | public class FixedLengthIntegrationTests : 10 | IntegrationTests> 11 | { 12 | private readonly IFixedLayout _layout; 13 | private readonly IFlatFileEngine _engine; 14 | private const string _testSource = @"00001Description 1 00003 15 | 00002Description 2 00003 16 | 00003Description 3 00003 17 | 00004Description 4 00003 18 | 00005Description 5 =Null 19 | 00006Description 6 00003 20 | 00007Description 7 00003 21 | 00008Description 8 00003 22 | 00009Description 9 00003 23 | 00010Description 10 =Null"; 24 | 25 | public FixedLengthIntegrationTests() 26 | { 27 | _layout = new FixedLayout() 28 | .WithMember(o => o.Id, set => set.WithLength(5).WithLeftPadding('0')) 29 | .WithMember(o => o.Description, set => set.WithLength(25).WithRightPadding(' ')) 30 | .WithMember(o => o.NullableInt, set => set.WithLength(5).AllowNull("=Null").WithLeftPadding('0')); 31 | 32 | _engine = new FixedLengthFileEngine(Layout, new FixedLengthLineBuilderFactory(), 33 | new FixedLengthLineParserFactory()); 34 | } 35 | 36 | protected override IFixedLayout Layout 37 | { 38 | get { return _layout; } 39 | } 40 | 41 | protected override IFlatFileEngine Engine 42 | { 43 | get { return _engine; } 44 | } 45 | 46 | public override string TestSource 47 | { 48 | get { return _testSource; } 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /src/FlatFile.Tests/FixedLength/FixedLengthLineParserTests.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | 3 | namespace FlatFile.Tests.FixedLength 4 | { 5 | using FlatFile.FixedLength; 6 | using FlatFile.FixedLength.Implementation; 7 | using FlatFile.Tests.Base.Entities; 8 | using FluentAssertions; 9 | 10 | public class FixedLengthLineParserTests 11 | { 12 | private readonly FixedLengthLineParser parser; 13 | private readonly IFixedLayout layout; 14 | 15 | public FixedLengthLineParserTests() 16 | { 17 | layout = new FixedLayout() 18 | .WithMember(o => o.Id, set => set.WithLength(5).WithLeftPadding('0')) 19 | .WithMember(o => o.Description, set => set.WithLength(25).WithRightPadding(' ')) 20 | .WithMember(o => o.NullableInt, set => set.WithLength(5).AllowNull("=Null").WithLeftPadding('0')); 21 | 22 | parser = new FixedLengthLineParser(layout); 23 | } 24 | 25 | [Theory] 26 | [InlineData("00001Description 1 00003", 1, "Description 1", 3)] 27 | [InlineData("00005Description 5 =Null", 5, "Description 5", null)] 28 | public void ParserShouldReadAnyValidString(string inputString, int id, string description, int? nullableInt) 29 | { 30 | var entry = new TestObject(); 31 | 32 | var parsedEntity = parser.ParseLine(inputString, entry); 33 | 34 | parsedEntity.Id.Should().Be(id); 35 | parsedEntity.Description.Should().Be(description); 36 | parsedEntity.NullableInt.Should().Be(nullableInt); 37 | } 38 | 39 | [Theory] 40 | [InlineData("00001Description 1 00003", 1, "Description 1", 3)] 41 | [InlineData("00005Description 5 ", 5, "Description 5", null)] 42 | [InlineData("00005Description 5 3", 5, "Description 5", 3)] 43 | public void ParserShouldSetValueNullValueIfStringIsToShort(string inputString, int id, string description, int? nullableInt) 44 | { 45 | var entry = new TestObject(); 46 | 47 | var parsedEntity = parser.ParseLine(inputString, entry); 48 | 49 | parsedEntity.Id.Should().Be(id); 50 | parsedEntity.Description.Should().Be(description); 51 | parsedEntity.NullableInt.Should().Be(nullableInt); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/FlatFile.Tests/FixedLength/FixedLengthMultiEngineTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using FlatFile.Core; 6 | using FlatFile.FixedLength; 7 | using FlatFile.FixedLength.Implementation; 8 | using FluentAssertions; 9 | using Xunit; 10 | 11 | namespace FlatFile.Tests.FixedLength 12 | { 13 | public class FixedLengthMultiEngineTests 14 | { 15 | readonly IFlatFileMultiEngine engine; 16 | 17 | const string TestData = @"Some Header To Skip 18 | STest Description 00042 19 | D20150323Another Description "; 20 | 21 | class Record1 22 | { 23 | public char Type { get; set; } 24 | public string Description { get; set; } 25 | public int Value { get; set; } 26 | 27 | public Record1() { Type = 'S'; } 28 | 29 | bool Equals(Record1 other) { return Type == other.Type && string.Equals(Description, other.Description) && Value == other.Value; } 30 | 31 | public override int GetHashCode() 32 | { 33 | unchecked 34 | { 35 | var hashCode = Type.GetHashCode(); 36 | hashCode = (hashCode * 397) ^ (Description != null ? Description.GetHashCode() : 0); 37 | hashCode = (hashCode * 397) ^ Value; 38 | return hashCode; 39 | } 40 | } 41 | 42 | public override bool Equals(object obj) 43 | { 44 | if (ReferenceEquals(null, obj)) return false; 45 | if (ReferenceEquals(this, obj)) return true; 46 | return obj.GetType() == GetType() && Equals((Record1) obj); 47 | } 48 | } 49 | 50 | class Record2 51 | { 52 | public char Type { get; set; } 53 | public string Date { get; set; } 54 | public string Description { get; set; } 55 | 56 | public Record2() { Type = 'D'; } 57 | 58 | bool Equals(Record2 other) { return Type == other.Type && string.Equals(Date, other.Date) && string.Equals(Description, other.Description); } 59 | 60 | public override int GetHashCode() 61 | { 62 | unchecked 63 | { 64 | var hashCode = Type.GetHashCode(); 65 | hashCode = (hashCode * 397) ^ (Date != null ? Date.GetHashCode() : 0); 66 | hashCode = (hashCode * 397) ^ (Description != null ? Description.GetHashCode() : 0); 67 | return hashCode; 68 | } 69 | } 70 | 71 | public override bool Equals(object obj) 72 | { 73 | if (ReferenceEquals(null, obj)) return false; 74 | if (ReferenceEquals(this, obj)) return true; 75 | return obj.GetType() == GetType() && Equals((Record2) obj); 76 | } 77 | } 78 | 79 | sealed class Record1Layout : FixedLayout 80 | { 81 | public Record1Layout() 82 | { 83 | WithMember(x => x.Type, c => c.WithLength(1)) 84 | .WithMember(x => x.Description, c => c.WithLength(20).WithRightPadding(' ')) 85 | .WithMember(x => x.Value, c => c.WithLength(5).WithLeftPadding('0')); 86 | } 87 | } 88 | 89 | sealed class Record2Layout : FixedLayout 90 | { 91 | public Record2Layout() 92 | { 93 | WithMember(x => x.Type, c => c.WithLength(1)) 94 | .WithMember(x => x.Date, c => c.WithLength(8)) 95 | .WithMember(x => x.Description, c => c.WithLength(20).WithRightPadding(' ')); 96 | } 97 | } 98 | 99 | public FixedLengthMultiEngineTests() 100 | { 101 | var layouts = new List> {new Record1Layout(), new Record2Layout()}; 102 | engine = new FixedLengthFileMultiEngine(layouts, 103 | (s, i) => 104 | { 105 | if (String.IsNullOrEmpty(s) || s.Length < 1) return null; 106 | 107 | switch (s[0]) 108 | { 109 | case 'S': 110 | return typeof (Record1); 111 | case 'D': 112 | return typeof (Record2); 113 | default: 114 | return null; 115 | } 116 | }, 117 | new FixedLengthLineBuilderFactory(), 118 | new FixedLengthLineParserFactory()) {HasHeader = true}; 119 | } 120 | 121 | [Fact] 122 | public void EngineShouldReadMultipleRecordTypes() 123 | { 124 | using (var stream = GetStringStream(TestData)) 125 | engine.Read(stream); 126 | 127 | var record1Results = engine.GetRecords().ToList(); 128 | var record2Results = engine.GetRecords().ToList(); 129 | 130 | record1Results.Should().HaveCount(1, "because it should skip the header and read one 'S' record"); 131 | record2Results.Should().HaveCount(1, "because there is one 'D' record"); 132 | 133 | record1Results.First().Should().Be(new Record1 {Description = "Test Description", Value = 42}); 134 | record2Results.First().Should().Be(new Record2 {Description = "Another Description", Date = "20150323"}); 135 | } 136 | 137 | static Stream GetStringStream(string s) 138 | { 139 | var memoryStream = new MemoryStream(); 140 | var writer = new StreamWriter(memoryStream); 141 | writer.Write(s); 142 | writer.Flush(); 143 | memoryStream.Position = 0; 144 | return memoryStream; 145 | } 146 | } 147 | } -------------------------------------------------------------------------------- /src/FlatFile.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("FlatFile.Tests")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("FlatFile.Tests")] 13 | [assembly: AssemblyCopyright("Copyright © 2014")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("a0043c60-5d89-4a32-81ac-bf121ef52a5e")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/FlatFile.Tests/Specifications/Defenitions/FixedLengthFileDefinitions.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Tests.Specifications.Defenitions 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Reflection; 7 | using FlatFile.Core; 8 | using FlatFile.Core.Base; 9 | using FlatFile.FixedLength; 10 | using FlatFile.FixedLength.Implementation; 11 | using FlatFile.Tests.Base.Entities; 12 | using FlatFile.Tests.Specifications.Entities; 13 | using FlatFile.Tests.Specifications.Extensions; 14 | using FluentAssertions; 15 | using TechTalk.SpecFlow; 16 | using TechTalk.SpecFlow.Assist; 17 | 18 | [Binding] 19 | public class FixedLengthFileDefinitions 20 | { 21 | [Given(@"I have specification for '(.*)' fixed-length type")] 22 | public void GivenIHaveSpecificationForType(string type, Table table) 23 | { 24 | var targetType = Assembly 25 | .GetExecutingAssembly() 26 | .GetTypes() 27 | .FirstOrDefault(x => x.FullName.EndsWith(type)); 28 | 29 | var properties = targetType 30 | .GetProperties(BindingFlags.Instance | BindingFlags.Public) 31 | .ToDictionary(info => info.Name); 32 | 33 | var typeMappings = table.CreateSet().ToArray(); 34 | 35 | var container = new FieldsContainer(); 36 | 37 | foreach (var typeMapping in typeMappings) 38 | { 39 | var propertyInfo = properties[typeMapping.Name]; 40 | 41 | var settings = new FixedFieldSettingsConstructor(propertyInfo); 42 | 43 | settings.WithLength(typeMapping.Length); 44 | 45 | if (!string.IsNullOrEmpty(typeMapping.NullValue)) 46 | { 47 | settings.AllowNull(typeMapping.NullValue); 48 | } 49 | 50 | switch (typeMapping.Padding) 51 | { 52 | case Padding.Right: 53 | settings.WithRightPadding(typeMapping.PaddingCharElement); 54 | break; 55 | case Padding.Left: 56 | settings.WithLeftPadding(typeMapping.PaddingCharElement); 57 | break; 58 | } 59 | 60 | container.AddOrUpdate(propertyInfo, settings); 61 | } 62 | 63 | var descriptor = new LayoutDescriptorBase(container) 64 | { 65 | HasHeader = false 66 | }; 67 | 68 | ScenarioContext.Current.Add(() => descriptor, descriptor); 69 | 70 | } 71 | 72 | [Given(@"I have several entities")] 73 | public void GivenIHaveSeveralEntities(IEnumerable testObjects) 74 | { 75 | var objects = testObjects.ToArray(); 76 | ScenarioContext.Current.Add("testObjects", objects); 77 | } 78 | 79 | [When(@"I convert entities to the fixed-length format")] 80 | public void WhenIConvertEntitiesToTheFlatFormat() 81 | { 82 | var fileEngineFactory = new FixedLengthFileEngineFactory(); 83 | 84 | var descriptor = ScenarioContext.Current.Get>("descriptor"); 85 | 86 | var fileEngine = fileEngineFactory.GetEngine(descriptor); 87 | 88 | var testObjects = ScenarioContext.Current.Get("testObjects"); 89 | 90 | var fileContent = fileEngine.WriteToString(testObjects); 91 | 92 | ScenarioContext.Current.Add(() => fileContent, fileContent); 93 | } 94 | 95 | [Then(@"^the result should be$")] 96 | public void ThenTheResultShouldBe(string multilineText) 97 | { 98 | var strings = multilineText.Split(new[] {Environment.NewLine}, StringSplitOptions.None); 99 | 100 | multilineText = string.Join(Environment.NewLine, strings); 101 | 102 | string fileContent = string.Empty; 103 | 104 | ScenarioContext.Current.TryGetValue(() => fileContent, out fileContent); 105 | 106 | fileContent.Should().Be(multilineText); 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/FlatFile.Tests/Specifications/Entities/FixedLengthTypeMapping.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Tests.Specifications.Entities 2 | { 3 | using FlatFile.FixedLength; 4 | 5 | public class FixedLengthTypeMapping 6 | { 7 | public string Name { get; set; } 8 | public int Length { get; set; } 9 | 10 | public string PaddingChar { get; set; } 11 | 12 | public char PaddingCharElement 13 | { 14 | get 15 | { 16 | if (PaddingChar == "") 17 | { 18 | PaddingChar = " "; 19 | } 20 | 21 | char element; 22 | 23 | if (!char.TryParse(PaddingChar, out element)) 24 | { 25 | element = '\0'; 26 | } 27 | 28 | return element; 29 | } 30 | } 31 | 32 | public Padding Padding { get; set; } 33 | 34 | public string NullValue { get; set; } 35 | } 36 | } -------------------------------------------------------------------------------- /src/FlatFile.Tests/Specifications/Extensions/FileEngineExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Tests.Specifications.Extensions 2 | { 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using FlatFile.Core; 6 | 7 | public static class FileEngineExtensions 8 | { 9 | public static string WriteToString(this IFlatFileEngine engine, IEnumerable source) 10 | where T : class, new() 11 | { 12 | using (var stream = new MemoryStream()) 13 | using (var reader = new StreamReader(stream)) 14 | { 15 | engine.Write(stream, source); 16 | stream.Position = 0; 17 | string fileContent = reader.ReadToEnd(); 18 | return fileContent; 19 | } 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /src/FlatFile.Tests/Specifications/Extensions/ScenarioContextExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Tests.Specifications.Extensions 2 | { 3 | using System; 4 | using System.Linq.Expressions; 5 | using FlatFile.Core.Extensions; 6 | using TechTalk.SpecFlow; 7 | 8 | public static class ScenarioContextExtensions 9 | { 10 | public static void Add(this ScenarioContext context, Expression> expression, object value) 11 | { 12 | var name = expression.GetMemberName(); 13 | context.Add(name, value); 14 | } 15 | 16 | public static bool TryGetValue(this ScenarioContext context, Expression> expression, out T value) 17 | { 18 | var name = expression.GetMemberName(); 19 | return context.TryGetValue(name, out value); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /src/FlatFile.Tests/Specifications/Extensions/StringExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Tests.Specifications.Extensions 2 | { 3 | public static class StringExtensions 4 | { 5 | public static int? ToNullableInt32(this string s) 6 | { 7 | int i; 8 | if (int.TryParse(s, out i)) 9 | { 10 | return i; 11 | } 12 | return null; 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /src/FlatFile.Tests/Specifications/FixedLengthFileMappingFeature.feature: -------------------------------------------------------------------------------- 1 | Feature: FixedLengthFileMappingFeature 2 | 3 | @ignore 4 | Scenario: Write fixed-length file 5 | Given I have specification for 'TestObject' fixed-length type 6 | | Name | Length | PaddingChar | Padding | NullValue | 7 | | Id | 5 | 0 | Left | | 8 | | Description | 25 | | Right | | 9 | | NullableInt | 5 | 0 | Left | =Null | 10 | And I have several entities 11 | | Id | Description | NullableInt | 12 | | 1 | Description 1 | 00003 | 13 | | 2 | Description 2 | 00003 | 14 | | 3 | Description 3 | 00003 | 15 | | 4 | Description 4 | 00003 | 16 | | 5 | Description 5 | =Null | 17 | | 6 | Description 6 | 00003 | 18 | | 7 | Description 7 | 00003 | 19 | | 8 | Description 8 | 00003 | 20 | | 9 | Description 9 | 00003 | 21 | | 10 | Description 10 | =Null | 22 | When I convert entities to the fixed-length format 23 | Then the result should be 24 | """ 25 | 00001Description 1 00003 26 | 00002Description 2 00003 27 | 00003Description 3 00003 28 | 00004Description 4 00003 29 | 00005Description 5 =Null 30 | 00006Description 6 00003 31 | 00007Description 7 00003 32 | 00008Description 8 00003 33 | 00009Description 9 00003 34 | 00010Description 10 =Null 35 | 36 | """ 37 | -------------------------------------------------------------------------------- /src/FlatFile.Tests/Specifications/Transforms/TransformsBinding.cs: -------------------------------------------------------------------------------- 1 | namespace FlatFile.Tests.Specifications.Transforms 2 | { 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using FlatFile.Tests.Base.Entities; 6 | using FlatFile.Tests.Specifications.Extensions; 7 | using TechTalk.SpecFlow; 8 | 9 | [Binding] 10 | public class TransformsBinding 11 | { 12 | [StepArgumentTransformation] 13 | public IEnumerable TestObjectsTransform(Table testObjectsTable) 14 | { 15 | return testObjectsTable 16 | .Rows 17 | .Select(r => new TestObject 18 | { 19 | Id = int.Parse(r["Id"]), 20 | Description = r["Description"], 21 | NullableInt = StringExtensions.ToNullableInt32(r["NullableInt"]) 22 | }).ToArray(); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /src/FlatFile.Tests/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/FlatFile.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FlatFile.Core", "FlatFile.Core\FlatFile.Core.csproj", "{1CB90052-B97A-4AD4-B9FD-20A22914D129}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FlatFile.FixedLength", "FlatFile.FixedLength\FlatFile.FixedLength.csproj", "{2D38BA1D-8D0C-4DC2-A7B1-7BA330D1DDCD}" 9 | EndProject 10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "assets", "assets", "{874AF755-A91B-434F-9679-35BEBC8B7D9F}" 11 | ProjectSection(SolutionItems) = preProject 12 | ..\appveyor.yml = ..\appveyor.yml 13 | ..\nuspecs\FlatFile.Core.Attributes.nuspec = ..\nuspecs\FlatFile.Core.Attributes.nuspec 14 | ..\nuspecs\FlatFile.Core.nuspec = ..\nuspecs\FlatFile.Core.nuspec 15 | ..\nuspecs\FlatFile.Delimited.Attributes.nuspec = ..\nuspecs\FlatFile.Delimited.Attributes.nuspec 16 | ..\nuspecs\FlatFile.Delimited.nuspec = ..\nuspecs\FlatFile.Delimited.nuspec 17 | ..\nuspecs\FlatFile.FixedLength.Attributes.nuspec = ..\nuspecs\FlatFile.FixedLength.Attributes.nuspec 18 | ..\nuspecs\FlatFile.FixedLength.nuspec = ..\nuspecs\FlatFile.FixedLength.nuspec 19 | ..\nuspecs\FlatFile.nuspec = ..\nuspecs\FlatFile.nuspec 20 | EndProjectSection 21 | EndProject 22 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FlatFile.Delimited", "FlatFile.Delimited\FlatFile.Delimited.csproj", "{F0478B76-5190-4B51-AA3A-C02D3A4109CA}" 23 | EndProject 24 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{58C25CA0-7F53-46A6-873E-1E1B18D65222}" 25 | EndProject 26 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FlatFile.Benchmark", "FlatFile.Benchmark\FlatFile.Benchmark.csproj", "{1484D999-2EC8-4D73-ACCC-17E25F98E20F}" 27 | EndProject 28 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FlatFile.Tests", "FlatFile.Tests\FlatFile.Tests.csproj", "{7B8FE44C-7725-40C2-AED4-7573F5ABAAB7}" 29 | EndProject 30 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FlatFile.Core.Attributes", "FlatFile.Core.Attributes\FlatFile.Core.Attributes.csproj", "{5849B415-6CC1-4615-A94F-265F5BD6F234}" 31 | EndProject 32 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FlatFile.Delimited.Attributes", "FlatFile.Delimited.Attributes\FlatFile.Delimited.Attributes.csproj", "{0313AD85-3109-4E8D-999C-D016943E83D5}" 33 | EndProject 34 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FlatFile.FixedLength.Attributes", "FlatFile.FixedLength.Attributes\FlatFile.FixedLength.Attributes.csproj", "{65154587-18F2-45DC-8E86-B2177309A479}" 35 | EndProject 36 | Global 37 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 38 | Debug|Any CPU = Debug|Any CPU 39 | Release|Any CPU = Release|Any CPU 40 | EndGlobalSection 41 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 42 | {1CB90052-B97A-4AD4-B9FD-20A22914D129}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 43 | {1CB90052-B97A-4AD4-B9FD-20A22914D129}.Debug|Any CPU.Build.0 = Debug|Any CPU 44 | {1CB90052-B97A-4AD4-B9FD-20A22914D129}.Release|Any CPU.ActiveCfg = Release|Any CPU 45 | {1CB90052-B97A-4AD4-B9FD-20A22914D129}.Release|Any CPU.Build.0 = Release|Any CPU 46 | {2D38BA1D-8D0C-4DC2-A7B1-7BA330D1DDCD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 47 | {2D38BA1D-8D0C-4DC2-A7B1-7BA330D1DDCD}.Debug|Any CPU.Build.0 = Debug|Any CPU 48 | {2D38BA1D-8D0C-4DC2-A7B1-7BA330D1DDCD}.Release|Any CPU.ActiveCfg = Release|Any CPU 49 | {2D38BA1D-8D0C-4DC2-A7B1-7BA330D1DDCD}.Release|Any CPU.Build.0 = Release|Any CPU 50 | {F0478B76-5190-4B51-AA3A-C02D3A4109CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 51 | {F0478B76-5190-4B51-AA3A-C02D3A4109CA}.Debug|Any CPU.Build.0 = Debug|Any CPU 52 | {F0478B76-5190-4B51-AA3A-C02D3A4109CA}.Release|Any CPU.ActiveCfg = Release|Any CPU 53 | {F0478B76-5190-4B51-AA3A-C02D3A4109CA}.Release|Any CPU.Build.0 = Release|Any CPU 54 | {1484D999-2EC8-4D73-ACCC-17E25F98E20F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 55 | {1484D999-2EC8-4D73-ACCC-17E25F98E20F}.Debug|Any CPU.Build.0 = Debug|Any CPU 56 | {1484D999-2EC8-4D73-ACCC-17E25F98E20F}.Release|Any CPU.ActiveCfg = Release|Any CPU 57 | {1484D999-2EC8-4D73-ACCC-17E25F98E20F}.Release|Any CPU.Build.0 = Release|Any CPU 58 | {7B8FE44C-7725-40C2-AED4-7573F5ABAAB7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 59 | {7B8FE44C-7725-40C2-AED4-7573F5ABAAB7}.Debug|Any CPU.Build.0 = Debug|Any CPU 60 | {7B8FE44C-7725-40C2-AED4-7573F5ABAAB7}.Release|Any CPU.ActiveCfg = Release|Any CPU 61 | {7B8FE44C-7725-40C2-AED4-7573F5ABAAB7}.Release|Any CPU.Build.0 = Release|Any CPU 62 | {5849B415-6CC1-4615-A94F-265F5BD6F234}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 63 | {5849B415-6CC1-4615-A94F-265F5BD6F234}.Debug|Any CPU.Build.0 = Debug|Any CPU 64 | {5849B415-6CC1-4615-A94F-265F5BD6F234}.Release|Any CPU.ActiveCfg = Release|Any CPU 65 | {5849B415-6CC1-4615-A94F-265F5BD6F234}.Release|Any CPU.Build.0 = Release|Any CPU 66 | {0313AD85-3109-4E8D-999C-D016943E83D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 67 | {0313AD85-3109-4E8D-999C-D016943E83D5}.Debug|Any CPU.Build.0 = Debug|Any CPU 68 | {0313AD85-3109-4E8D-999C-D016943E83D5}.Release|Any CPU.ActiveCfg = Release|Any CPU 69 | {0313AD85-3109-4E8D-999C-D016943E83D5}.Release|Any CPU.Build.0 = Release|Any CPU 70 | {65154587-18F2-45DC-8E86-B2177309A479}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 71 | {65154587-18F2-45DC-8E86-B2177309A479}.Debug|Any CPU.Build.0 = Debug|Any CPU 72 | {65154587-18F2-45DC-8E86-B2177309A479}.Release|Any CPU.ActiveCfg = Release|Any CPU 73 | {65154587-18F2-45DC-8E86-B2177309A479}.Release|Any CPU.Build.0 = Release|Any CPU 74 | EndGlobalSection 75 | GlobalSection(SolutionProperties) = preSolution 76 | HideSolutionNode = FALSE 77 | EndGlobalSection 78 | GlobalSection(NestedProjects) = preSolution 79 | {1484D999-2EC8-4D73-ACCC-17E25F98E20F} = {58C25CA0-7F53-46A6-873E-1E1B18D65222} 80 | {7B8FE44C-7725-40C2-AED4-7573F5ABAAB7} = {58C25CA0-7F53-46A6-873E-1E1B18D65222} 81 | EndGlobalSection 82 | EndGlobal 83 | -------------------------------------------------------------------------------- /src/SharedAssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Runtime.InteropServices; 4 | 5 | [assembly: AssemblyProduct("FlatFile")] 6 | [assembly: AssemblyCompany("Pavel Nasovich")] 7 | [assembly: AssemblyCopyright("Copyright © 2014 Pavel Nasovich")] 8 | [assembly: AssemblyCulture("")] 9 | 10 | [assembly: ComVisible(false)] 11 | [assembly: CLSCompliant(false)] 12 | 13 | // Don't edit manually! Use `build.bat version` command instead! 14 | [assembly: AssemblyVersion("1.0.0")] 15 | [assembly: AssemblyFileVersion("1.0.0.0")] --------------------------------------------------------------------------------