Search code examples
c#genericsfilehelpers

Can I parameterize generic Type


We are having several reports in fixed length record format. We are using FileHelpers for transforming them to delimited record format.

As there are serveral reports we thought of describing the fixed and delimited models and pass to

FileTransformEngine<TSource, TDestination>();

As to make it DRY can we do something like

Transform<TInput, TOutput>() 
{ 
var engine = new FileTransformEngine<TInput, TOutput>(); 
engine.TransformFileFast(...); 
} 

I'm new to C# and generics and I'm not sure where to start.

Can anyone can give me some guidance, whether this is possible, as all models are already created they are available at compile time I think.


Solution

  • The documentation for filehelpers shows how to read a fixed file and write a delimited file - so it should be pretty easy to wrap calls to both in your own FileTransformEngine

    public class FileTransformEngine<T>
    {
        public void TransformFileFast(string inputFile, string outputFile)
        {
           var readEngine = new FixedFileEngine<T>();
           T[] records = readEngine.ReadFile(inputFile);
           var writeEngine = new FileHelperEngine<T>();
           writeEngine.WriteFile(outputFile,records);       
    
        }
    }
    

    For this to work, your class will need the attributes for both reading and writing. eg

    [FixedLengthRecord()]
    [DelimitedRecord("|")]
    public class MyRecord
    {
         [FieldFixedLength(5)] // for reading
         [FieldConverter(ConverterKind.Decimal, ".")] // for writing
         public decimal Foo{get; set; }
    }
    

    Then you would use

    var engine = new FileTransformEngine<MyRecord>();
    engine.TransformFileFast("from/input.txt","to/output.csv");
    

    If you want different types for input and output you could have the class take two types (an input and an output) along with a predicate for transforming one to the other.

    public class FileTransformEngine<TInput, TOutput>
    {
        public void TransformFileFast(string inputFile, string outputFile, 
                                          Func<TInput,TOutput> transformer)
        {
           var readEngine = new FixedFileEngine<TInput>();
           TInput[] records = readEngine.ReadFile(inputFile);
           IEnumerable<TOutput> outputRecords = records.Select(transformer);
           var writeEngine = new FileHelperEngine<TOutput>();
           writeEngine.WriteFile(outputFile,outputRecords );       
    
        }
    }
    

    This would then be called with your two types

    var engine = new FileTransformEngine<MyInputRecord, MyOutputRecord>();
    engine.TransformFileFast("from/input.txt","to/output.csv", input => {
        //transform input to output.
        return new MyOutputRecord(); 
    });