Атрибуты полей в базовом классе используются в производном классе при чтении
Я пытаюсь использовать полиморфизм правильно, чтобы избежать тонны лишнего кода, но файловый движок выдает ошибки, как если бы он использовал базовый класс вместо производного класса.
Идеальная ситуация:
- создать базовый класс для чтения
- пользователь загружает файл и выбирает тип файла из выпадающего
- раскрывающийся список запускает производный класс, который используется в библиотеке FileHelpers для чтения загруженного файла
Я не уверен, как правильно использовать полиморфизм в этом случае, так как библиотека помощников файлов требует, чтобы у вас были поля для чтения из 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;
}
Производный класс читатель класса:
[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);
...
}
}
По какой-то причине, когда я пытаюсь использовать свой производный класс в движке filehelpers (см. Выше), он не может обработать FieldTrim
атрибуты, и, кажется, вытащить из базового класса, но я не уверен, почему.
Я открыт для любых предложений, чтобы иметь базовый класс, из которого я могу извлечь.
2 ответа
Вы дублируете поля в производном классе. Класс уже унаследует всех этих членов. Если ваша проблема заключается в том, что вам нужно подать FieldTrim
атрибуты для различных подклассов, вы можете попробовать сделать UploadedFilebase
интерфейс вместо:
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; }
}
Сложность в том, как это будет работать с библиотекой "FileHelpers", которую вы используете. В идеале вы хотели бы сделать свои поля приватными, с общедоступными свойствами, но я не уверен, что вы можете применять их FieldTrim
и другие атрибуты для частных полей или свойств, которые будут вашими двумя вариантами.
Я бы также предложил переосмыслить, нужен ли вам здесь полиморфизм. Вы собираетесь ссылаться на разнородные коллекции UploadedFileBase
? Или вы просто воплощаете вещи таким образом, чтобы быть "модным"? В частности, способ, которым вы разработали свой абстрактный класс с открытыми полями, на самом деле не очень хороший дизайн. Может быть, лучше сначала реализовать ваши конкретные классы, а затем перенести любую избыточность, которую вы видите, в базовый класс или интерфейс, если это улучшит дизайн.
Вы скрываете свойства своего базового класса и, следовательно, всякий раз, когда вы ссылаетесь на них, вы не получаете нужные значения.
Вам нужно добавить virtual
ключевое слово перед всеми вашими свойствами в вашем базовом классе. Вы по сути дублируете их, когда переопределяете их в AmexBaseRead.
Для подробного объяснения посмотрите следующую статью MSDN: http://msdn.microsoft.com/en-us/library/ms173152.aspx