Search code examples
c#architecturepolymorphismfilehelpers

Field Attributes on base class are used in Derived Class when reading


I'm trying to use polymorphism correctly to avoid a ton of extra code, but the file engine appears to throw errors as if it were using the base class instead of the derived class.

Ideal situation:

  • create a read base class
  • user uploads a file, and selects what type of file it is from drop down
  • the drop down starts a derived class, which is used in the FileHelpers library to read the uploaded file

I'm not sure how to correctly use polymorphism in this instance, since the file helpers library needs you to have fields to read from the CSV.

public abstract class UploadedFilebase
{
    public string CaseId;        
    public string ChargeReference;
    public Double Amount;
    public DateTime ReceivedDate;        
    public string ReasonCode;        
    public string ReplyBy;        
    public string Resolution;        
    public Double ChargeAmount;
}

Derived Class reader class:

[DelimitedRecord(","), IgnoreFirst(9), IgnoreLast(1)]
public class AmexBaseRead : UploadedFilebase, IUploadedFileReader 
{
    [FieldTrim(TrimMode.Left, "'")]
    public string CaseId;

    [FieldTrim(TrimMode.Left, "'")]
    public string ChargeReference;

    [FieldTrim(TrimMode.Both, "'($)")]
    public new Double Amount;

    [FieldTrim(TrimMode.Left, "'")]
    [FieldConverter(ConverterKind.Date, "MM/dd/yyyy")]
    public DateTime ReceivedDate;

    [FieldTrim(TrimMode.Left, "'")]
    public string ReasonCode;

    [FieldTrim(TrimMode.Left, "'")]
    public string ReplyBy;

    [FieldTrim(TrimMode.Left, "'")]
    public string Resolution;

    [FieldTrim(TrimMode.Left, "'$")]
    public Double ChargeAmount;

    SingleImportResult IUploadedFileReader.ReadFromFile(HttpPostedFileBase fileToRead
    {
        ...

        FileHelperEngine<AmexBaseRead> engine = new FileHelperEngine<AmexBaseRead>();
        engine.ErrorManager.ErrorMode = ErrorMode.SaveAndContinue;
        TextReader tr = new StreamReader(fileToRead.InputStream);
        AmexBaseRead[] records = engine.ReadStream(tr);

        ...
    }
}

For some reason when I try to use my derived class in the filehelpers engine (above), it can't process the FieldTrim attributes, and it seems to pull from the base class, but I'm not sure why.

I'm open to any suggestions to have a base class that I can derive from.


Solution

  • You're duplicating the fields in the derived class. The class will already inherit all of those members. If your issue is that you need to apply different FieldTrim attributes to different subclasses, you might try making UploadedFilebase an interface instead:

    public interface IUploadedFilebase
    {
        string CaseId { get; }
        string ChargeReference { get; }
        Double Amount { get; }
        DateTime ReceivedDate { get; }
        string ReasonCode { get; }
        string ReplyBy { get; }
        string Resolution { get; }
        Double ChargeAmount { get; }
    }
    

    The tricky part is how that would work with the "FileHelpers" library you're using. You would ideally want to make your fields private, with public properties, but I'm not sure whether you can apply those FieldTrim and other attributes to private fields, or to properties, which would be your two options.

    I would also suggest rethinking whether you actually need polymorphism here. Are you intending to refer to heterogeneous collections of UploadedFileBase? Or are you just implementing things this way to be "fancy"? In particular, the way you have designed your abstract class, with public fields, is not really very good design. It may be better to first implement your concrete classes, and then later push any redundancy you see up into a base class or interface, if that would improve the design.