简体   繁体   English

如何对具有多个XmlElementAttributes的对象使用automapper?

[英]How do I use automapper for objects with multiple XmlElementAttributes?

I'm having problems setting up automapper for objects generated in a .cs file from a .xsd. 我在从.xsd为.cs文件中生成的对象设置automapper时遇到问题。

Not really sure how to go about solving the issue when an object has multiple attributes as shown below: 当对象具有多个属性时,不确定如何解决问题,如下所示:

Been looking at TypeConverters etc, but not really sure how to properly set it up. 一直在看TypeConverters等,但不确定如何正确设置它。 Been using automapper for a while now and having no issues as long as there's not multiple attributes connected to one member. 一直在使用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;
        }
    }
}

The issue I have is that I don't know how to set it up so customerInfo gets correctly mapped depending on some value in "Info". 我遇到的问题是我不知道如何设置它,以便根据“信息”中的某些值正确映射customerInfo。

For example, if "Info" contains "age" and "id" it should be mapped to customerInfoEnhanced etc. 例如,如果“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));
}

Here's the code for the serializer aswell: 这是序列化器的代码:

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);
}

If I set .ForMember(x => x.customerInfo, x => x.MapFrom(y => (Object)null)); 如果我设置.ForMember(x => x.customerInfo, x => x.MapFrom(y => (Object)null)); the code works and "actual" gives me a list with item = null as expected, so I know the issue is with mapping "Item" in customerInfo. 代码工作,“实际”给我一个item = null的列表,所以我知道问题是在customerInfo中映射“Item”。

I expect the mapper to map to the correct class, right now I get either Missing type map or "Info was not expected. Use the XmlInclude or SoapInclude attribute to specify types that are not known statically. 我希望映射器映射到正确的类,现在我得到Missing类型映射或“Info is not expected。使用XmlInclude或SoapInclude属性指定静态未知的类型。

Would really appreciate some pointers on how to solve the issue! 真的很感激如何解决这个问题的一些指示!

Solved it for my own needs, solution down below if someone else encounters the same issue. 解决它是为了我自己的需要,如果其他人遇到同样的问题解决方案。

The solution for me was to use the ResolveUsing instead of MapFrom for the specific properties that had multiple tag names and using Mapper.Map with the correct classes for the different cases. 对我来说,解决方案是使用ResolveUsing而不是MapFrom来获取具有多个标记名称的特定属性,并使用Mapper.Map以及针对不同情况的正确类。

Full code looks like this: 完整代码如下所示:

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);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM