csvHelper приведение от одного объекта к другому в картографе

Я использую CsvHelper и пытаюсь сопоставить различные свойства на основе значения определенного свойства.

Map(m => (m.Prop1 == Enum.Setting1 || m.Prop1 == Enum.Setting2)? m.Prop2 : m.Prop3).Name("MyProperty");

Это не работает, вызывая исключение:

System.ArgumentException : не член доступа Имя параметра: выражение

Поэтому я подумал, что попробую создать новый класс, наследующий от моего базового объекта, а затем указать его в типе сопоставления.

Где этот новый тип буквально выполняет эту логику в свойстве.

public class NewClassCsv : BaseClass
{
    public string MyProperty
    {
        get { return (this.Prop1 == Enum.Setting1 || this.Prop1 == Enum.Setting2) ? this.Prop2 : this.Prop3; }
    }

Я попытался использовать этот новый класс в качестве типа карты, но объект, поступающий в метод WriteRecords помощника, является базовым типом, и это не приводит к его изменению.

Поэтому я попытался сделать приведение к отображению:

Map(x => ((NewClassCsv)x).MyProperty);

Это тоже не сработало и не нашло свойство на объекте.

Кто-нибудь сталкивался с этим и знает, как решить?

Редактировать: раздел пользовательского картографа

csvWriter.Configuration.RegisterClassMap<CustomMap>();

public class CustomMap: CsvClassMap<NewClassCsv>
{
    public override void CreateMap()
    {
        Map(m => m.MyProperty).Name("MyProperty");
    }
}

person jimplode    schedule 12.01.2016    source источник
comment
Я думаю, вам нужен собственный картограф; joshclose.github.io/CsvHelper/#mapping-runtime-mapping   -  person drneel    schedule 12.01.2016
comment
Я уже использую пользовательский маппер, но кастинг, похоже, не работает, обновленный вопрос с моим настраиваемым маппером   -  person jimplode    schedule 13.01.2016


Ответы (1)


Хорошо, я пытался сделать то, что просто невозможно.

Во-первых, я не могу преобразовать базовый класс в производный класс — я должен был знать лучше.

Однажды я понял, что решил, что у меня есть пара вариантов:

  1. Вручную создайте CSV в foreach (не понравился этот подход)
  2. Просто добавьте свойства отображения к существующему объекту (это казалось грязным и неправильным).
  3. Используйте AutoMapper и используйте его для преобразования из одного сложного типа в плоскую структуру, которую я хочу, а затем просто используйте свойства прямо оттуда.

Я, конечно, выбрал вариант 3:

 //mappings for csv download
        Mapper.CreateMap<TeamFeedMessage, MessageCsv>()
              .ForMember(dest => dest.Alias, opt => opt.MapFrom(t => (t.Message.Contributor.Channel == ChannelEnum.GnipTwitter || t.Message.Contributor.Channel == ChannelEnum.Twitter)? t.Message.Contributor.UserName : t.Message.Contributor.Alias))

public sealed class TeamFeedMessageMap : CsvClassMap<MessageCsv>
{
    public TeamFeedMessageMap()
    {
        AutoMap();
    }
}

Затем с его помощью:

 var newCsvData = Mapper.Map<IEnumerable<TeamFeedMessage>, List<MessageCsv>>(reportData) as IEnumerable;

csvWriter.Configuration.RegisterClassMap<TeamFeedMessageMap>();

csvWriter.WriteRecords(newCsvData);
person jimplode    schedule 13.01.2016