Как использовать automapper для объектов с несколькими XmlElementAttributes? - PullRequest
0 голосов
/ 02 апреля 2019

У меня проблемы с настройкой автоматического обработчика объектов, сгенерированных в файле .cs из .xsd.

Не совсем уверен, как решить проблему, когда объект имеет несколько атрибутов, как показано ниже:

Я смотрел на TypeConverters и т. Д., Но не совсем уверен, как правильно его настроить.Уже некоторое время я использую automapper и не испытываю проблем, если к одному элементу не подключено несколько атрибутов.

public partial class customerInfo {

    private object itemField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("customerInfoBasic", typeof(customerInfoBasic))]
    [System.Xml.Serialization.XmlElementAttribute("customerInfoSimple", typeof(customerInfoSimple))]
    [System.Xml.Serialization.XmlElementAttribute("customerInfoEnhanced", typeof(customerInfoEnhanced))]
    public object Item {
        get {
            return this.itemField;
        }
        set {
            this.itemField = value;
        }
    }
}

public partial class customerInfoBasic{

    private string nameField;

    /// <remarks/>
    public string name {
        get {
            return this.nameField;
        }
        set {
            this.nameField= value;
        }
    }
}

public partial class customerInfoSimple{

    private string nameField;
    private string idField;


    /// <remarks/>
    public string name {
        get {
            return this.nameField;
        }
        set {
            this.nameField= value;
        }
    }

    public string id {
        get {
            return this.idField;
        }
        set {
            this.idField= value;
        }
    }
}

public partial class customerInfoEnhanced{

    private string nameField;
    private string idField;
    private string ageField;

    /// <remarks/>
    public string name {
        get {
            return this.nameField;
        }
        set {
            this.nameField= value;
        }
    }

    public string id {
        get {
            return this.idField;
        }
        set {
            this.idField= value;
        }
    }

    public string age {
        get {
            return this.ageField;
        }
        set {
            this.ageField= value;
        }
    }
}

Проблема у меня заключается в том, что я не знаю, как ее настроить, так customerInfoкорректно отображается в зависимости от некоторого значения в «Инфо».

Например, если «Info» содержит «age» и «id», оно должно быть сопоставлено с customerInfoEnhanced и т. Д.

public static void AddSessionTransformationMappings(IMapperConfiguration cfg)
{
    cfg.AllowNullCollections = true;

    cfg.CreateMap<IEnumerable<Info>, customerInfoList>()
        .ForMember(x => x.customerInfo, x => x.MapFrom(y => y));

    cfg.CreateMap<Info, customerInfo>()
        .ForMember(x => x.Item, x => x.MapFrom(y => y));

    cfg.CreateMap<Info, customerInfoBasic>()
        .ForMember(x => x.Name, x => x.MapFrom(y => y.name));

    cfg.CreateMap<Info, customerInfoSimple>()
        .ForMember(x => x.Name, x => x.MapFrom(y => y.name))
        .ForMember(x => x.Id, x => x.MapFrom(y => y.id));

    cfg.CreateMap<Info, customerInfoEnhanced>()
        .ForMember(x => x.Name, x => x.MapFrom(y => y))
        .ForMember(x => x.Id, x => x.MapFrom(y => y.id))
        .ForMember(x => x.Age, x => x.MapFrom(y => y.age));
}

Ниже приведен код для сериализатора:

var output = provider.Transform(new List<Info> { input });

customerInfoList actual = null;
XmlSerializer serializer = new XmlSerializer(typeof(customerInfoList));
using (MemoryStream ms = new MemoryStream())
{
    serializer.Serialize(ms, output);
    ms.Position = 0;
    actual = (customerInfoList)serializer.Deserialize(ms);
}

Если я установлю .ForMember(x => x.customerInfo, x => x.MapFrom(y => (Object)null));, код работает, и «фактический» дает мне список с item = null, как и ожидалось, поэтому я знаю, что проблема связана с отображением «Item» в customerInfo.

Iожидаю, что маппер отобразится в правильный класс, сейчас я получаю либо карту отсутствующего типа, либо «Информация не ожидалась». Используйте атрибут XmlInclude или SoapInclude, чтобы указать типы, которые статически не известны.

Был бы очень признателен за некоторыеуказатели на то, как решить проблему!

1 Ответ

0 голосов
/ 02 апреля 2019

Решено для моих собственных нужд, решение ниже, если кто-то еще сталкивается с той же проблемой.

Для меня было решение использовать ResolveUsing вместо MapFrom для конкретных свойств, которые имели несколько имен тегов, и используяMapper.Map с правильными классами для разных случаев.

Полный код выглядит следующим образом:

public static void AddSessionTransformationMappings(IMapperConfiguration cfg)
{
    cfg.AllowNullCollections = true;

    cfg.CreateMap<IEnumerable<Info>, customerInfoList>()
        .ForMember(x => x.customerInfo, x => x.MapFrom(y => y));

    cfg.CreateMap<Info, customerInfo>()
        .ForMember(x => x.Item, x => x.ResolveUsing(y => CustomerInfoLevel(y)));

    cfg.CreateMap<Info, customerInfoBasic>()
        .ForMember(x => x.Name, x => x.MapFrom(y => y.name));

    cfg.CreateMap<Info, customerInfoSimple>()
        .ForMember(x => x.Name, x => x.MapFrom(y => y.name))
        .ForMember(x => x.Id, x => x.MapFrom(y => y.id));

    cfg.CreateMap<Info, customerInfoEnhanced>()
        .ForMember(x => x.Name, x => x.MapFrom(y => y.name))
        .ForMember(x => x.Id, x => x.MapFrom(y => y.id))
        .ForMember(x => x.Age, x => x.MapFrom(y => y.age));
}

private static Object CustomerInfoLevel(Info info)
{
    if (info.age != null)
    {
        return Mapper.Map<customerInfoEnhanced>(info);
    }
    else if (info.id != null)
    {
        return Mapper.Map<customerInfoSimple>(info);
    }
    else
    {
        return Mapper.Map<customerInfoBasic>(info);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...