Map xml string property to C# properties

匿名 (未验证) 提交于 2019-12-03 01:44:01

问题:

I need to map a xml property to c# properties.

var src = new Source(); src.Id = 1; src.Name = "Test"; src.Address = "<Country>MyCountry</Country><Prefecture>MyPrefecture</Prefecture><City>MyCity</City>";  class Source { public string ID{ get; set; } public string Name{ get; set; } public string Address{ get; set; } }                  Class Destination         {         public string ID{ get; set; }         public string Name{ get; set; }         public string Country { get; set;}         public string Prefecture { get; set;}         public string City { get; set;}         } 

Is it possible to achieve it through AutoMapper?

回答1:

You can do the following. Considering your source type.

var src = new Source(); src.ID = 1; src.Name = "Test"; src.Address = "<Country>MyCountry</Country><Prefecture>MyPrefecture</Prefecture><City>MyCity</City>"; 

Since your source type (src.Address) doesn't have a root element, let's add one and parse the xml to a XDocument.

XDocument xdoc = new XDocument(); xdoc = XDocument.Parse($"<Root>{src.Address}</Root>"); 

Now during Initializing of Automapper, you need to map fields.

Mapper.Initialize(cfg =>            cfg.CreateMap<XElement, Destination>()                .ForMember(dest => dest.Country, opt => opt.MapFrom(x=>x.Element(nameof(Destination.Country)).Value))                .ForMember(dest => dest.City, opt => opt.MapFrom(x => x.Element(nameof(Destination.City)).Value))                .ForMember(dest => dest.Prefecture, opt => opt.MapFrom(x => x.Element(nameof(Destination.Prefecture)).Value))); 

Now you can resolve it as following.

 Destination result = Mapper.Map<XElement, Destination>(xdoc.Root); 

Update

You can using ConstructUsing as well for the purpose, that would hide away the Xml related code away from your other codes.

var src = new Source(); src.ID = "1"; src.Name = "Test"; src.Address = "<Country>MyCountry</Country><Prefecture>MyPrefecture</Prefecture><City>MyCity</City>";  XDocument xdoc = new XDocument(); xdoc = XDocument.Parse($"<Root>{src.Address}</Root>");  Mapper.Initialize(cfg =>                     cfg.CreateMap<Source, Destination>()                     .ConstructUsing(x=>ConstructDestination(x))                  ); 

Where ConstructDestination is defined as

static Destination ConstructDestination(Source src) {    XDocument xdoc = new XDocument();    xdoc = XDocument.Parse($"<Root>{src.Address}</Root>");     return new Destination    {      Country = xdoc.Root.Element(nameof(Destination.Country)).Value,      City = xdoc.Root.Element(nameof(Destination.City)).Value,      Prefecture = xdoc.Root.Element(nameof(Destination.Prefecture)).Value,    };   } 

Your client code looks much cleaner now.

Destination result = Mapper.Map<Source, Destination>(src); 


回答2:

One option could be to wrap it with a root node and use a serializeable class.

The class would look like this:

[Serializable] public class Address {     public string Country { get; set; }     public string Prefecture { get; set; }     public string City { get; set; } } 

Deserialize would looke like the following:

        string xml = "<Country>MyCountry</Country><Prefecture>MyPrefecture</Prefecture><City>MyCity</City>";         string wrapped = $"<Address>{xml}</Address>";         XmlSerializer serializer = new XmlSerializer(typeof(Address));         Address addr = (Address)serializer.Deserialize(new StringReader(wrapped)); 


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!