Search code examples
c#constructorfilehelpers

How to do inhereted empty constructor when Base class has constructor with parameters


i.e. I've got a class Box with properties length, height, width and constructor "Box(int witdth, int height, int length)". Got an inhereted class ProductBox with property Name. I've also got a .csv file which I parse to ProductBox with FileHelpers library, so my constructor's empty. For now I can't inherete ProductBox from Box, because Box has not-empty constructor, and in FileHelpers the constructor's empty. Is there a way to inherete ProductBox from Box?

class Box
{
    int Width;
    int Height;
    int Length;

    public Box(int width, int height, int length)
    {
        this.Width = width;
        this.Height = height;
        this.Length = length;
    }
}

class ProductBox : Box
{
    string Name;
    int Width;
    int Height;
    int Length;
    public static ProductBox[] GetInfo(string filePath)
    {
        var engine = new FileHelperEngine<ProductBox>();
        var result = engine.ReadFile(filePath);
        return result;
    }
}

Solution

  • From a design perspective, I think you are going about it the wrong way. While you might be able to hack something together to solve your constructor problem, you are trying to use the Box class for two incompatible uses. Instead you should have two separate classes.

    FileHelpers is a library for describing csv files so that you can import them easily. You should have a BoxFileSpec for describing your file. It's really not a proper C# class - it may have: dummy fields to represent unused columns; lots of attributes [FieldNullValue], [FieldQuoted], [FieldConverter]; etc. It works best with public fields (a FileHelpers limitation which is not C# best practice), etc. It is a convenience syntax for describing the import file. It should not include any logic or special constructors.

    Then you can have a clean best-practices Box class which has your specialized constructors and additional logic, properties, methods, whatever.

    Then you use a FileHelperEngine<BoxFileSpec> to read the records into an array and map it to an enumerable of Box (via Linq or a library like AutoMapper).

    Something like:

    /// A 'real' class. Add methods, getters, setters, whatever.
    /// FileHelpers doesn't use this class.
    class Box
    {
        public int Width { get; set; }
        public int Height { get; set; }
        public int Length { get; set; }
    
        public Box(int width, int height, int length)
        {
            this.Width = width;
            this.Height = height;
            this.Length = length;
        }
    }
    
    /// A 'real' class. Add methods, getters, setters, whatever.
    /// FileHelpers doesn't use this class.
    class ProductBox : Box
    {
        public ProductBox(int width, int height, int length) 
            : base(width, height, length)
        { }
    
        public int Name { get; set; }
    }
    
    /// This is the class FileHelpers will use
    /// This class describes the CSV file only. Stick to whatever
    /// syntax conventions are required by FileHelpers.
    [DelimitedRecord(";")]
    class ProductBoxFileSpec
    {
        [FieldQuoted(QuoteMode.OptionalForRead)]
        public int Width;
        [FieldQuoted(QuoteMode.OptionalForRead)]
        public int Height;
        [FieldQuoted(QuoteMode.OptionalForRead)]
        // Handle non-US formats such as , decimal points
        // convert from inches to centimetres? 
        // you get the idea...
        [FieldConverter(MyCustomizedLengthConverter)] 
        public int Length;
        [FieldOptional]
        public string SomeDummyExtraCSVColumn;
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            var engine = new FileHelperEngine<ProductBoxFileSpec>();
            var productBoxRecords = engine.ReadFile(filePath);
            var productBoxes = productBoxRecords
                .Select(x => new ProductBox(x.Width, x.Height, x.Length) { Name = x.Name });
        }
    }