2011-07-01 40 views
7

Nếu tôi có các lớp sau:Automapper để tạo đối tượng từ XML

class SPUser 
{ 
    public int ID { get; set; } 

    public string Name { get; set; } 
    public string LoginName { get; set; } 
    public string Email { get; set; } 

    public bool IsSiteAdmin { get; set; } 
    public bool IsSiteAuditor { get; set; } 
    public bool IsDomainGroup { get; set; } 

    public List<SPGroup> Groups { get; set; } 
} 

Và tôi đang sử dụng các dịch vụ web SharePoint, mà trả về một XML với một thuộc tính cho mỗi tài sản trên lớp học của tôi, chẳng hạn như:

<Users> 
    <User Name="name" Description="desc" ..... /> 
</Users> 

Có cách nào để sử dụng AutoMapper để ánh xạ đoạn XML thành một phiên bản lớp SPUser không?

Trả lời

8

Blog đã bị xóa - đây là các kho lưu trữ Bing của bài bởi @DannyDouglass

Đơn giản hóa sử dụng XML dữ liệu Với AutoMapper và LINQ-to-Xml

Gần đây tôi đã chạy vào một kịch bản tại nơi làm việc yêu cầu tự tiêu thụ một số dịch vụ web SOAP, mà tôi chắc chắn bạn có thể tưởng tượng là khá đơn điệu. Một đồng nghiệp (Seth Carney) và tôi đã thử một vài cách tiếp cận khác nhau, nhưng cuối cùng chúng tôi đã giải quyết một giải pháp đơn giản hóa việc tiêu thụ xml và cuối cùng làm cho mã dễ kiểm tra hơn. Giải pháp đó tập trung vào việc tận dụng AutoMapper, một công cụ ánh xạ đối tượng nguồn mở, để tạo ra một liên kết giữa XElements (http://msdn.microsoft.com/en-us/library/system.xml.linq.xelement.aspx) được trả lại trong các thông điệp SOAP và các hợp đồng tùy chỉnh mà chúng ta đã tạo - theo cách có thể tái sử dụng.

Tôi tổng hợp một bản trình diễn nhanh cho thấy cách bạn có thể sử dụng cùng một cách tiếp cận để tiêu thụ và hiển thị Dòng thời gian công cộng của Twitter (http://api.twitter.com/1/statuses/public_timeline.xml) (sử dụng loại phản hồi Xml của API).

Lưu ý: Các mã nguồn cho các ví dụ sau đây có thể được tìm thấy trên trang GitHub của tôi: https://github.com/DannyDouglass/AutoMapperXmlMappingDemo

  1. Bắt Setup Project

Sau khi tạo một MVC3 cơ bản (beta tải) dự án và dự án thử nghiệm liên quan, bước đầu tiên là cài đặt gói AutoMapper.Tôi đã sử dụng NuGet, hệ thống quản lý gói được công bố gần đây của Microsoft, để cài đặt bất kỳ phụ thuộc nguồn mở nào. Các lệnh sau đây là tất cả những gì là cần thiết để thiết lập AutoMapper trong dự án MVC3 tôi (đọc thêm về NuGet đây (http://weblogs.asp.net/scottgu/archive/2010/10/06/announcing-nupack-asp-net-mvc-3-beta-and-webmatrix-beta-2.aspx) và tại đây (http://weblogs.asp.net/scottgu/archive/2010/10/06/announcing-nupack-asp-net-mvc-3-beta-and-webmatrix-beta-2.aspx)):

PM> add-package AutoMapper 
  1. Tạo Mapping

Với AutoMapper được cài đặt Tôi đã sẵn sàng bắt đầu tạo các thành phần cần thiết cho ánh xạ xml-đối tượng. Bước đầu tiên là tạo hợp đồng nhanh được sử dụng trong đơn đăng ký của tôi để đại diện cho đối tượng Tweet:

public interface ITweetContract 
{ 
ulong Id { get; set; } 
string Name { get; set; } 
string UserName { get; set; } 
string Body { get; set; } 
string ProfileImageUrl { get; set; } 
string Created { get; set; } 
} 

Không có gì điên rồ ở đây - chỉ là một thực thể đơn giản. Đây là tất cả các trường được cung cấp trong phản hồi từ API Twitter sử dụng tên khác cho một số trường. Trong những trường hợp đơn giản mà nguồn và đích đối tượng có cùng tên bạn có thể thiết lập một bản đồ rất nhanh chóng sử dụng cú pháp sau:

Mapper.CreateMap<SourceObj, DestinationObj>(); 

Tuy nhiên, AutoMapper không hỗ trợ Xml theo mặc định tôi phải xác định các lĩnh vực mà tôi sẽ ánh xạ. Sử dụng API thông thạo trong AutoMapper Tôi có thể tạo chuỗi ánh xạ trường của mình. Hãy xem xét một ví dụ lĩnh vực ánh xạ trong ví dụ của tôi - của tweet Body:

Mapper.CreateMap<XElement, ITweetContract>() 
.ForMember(
    dest => dest.Body, 
    options => options.ResolveUsing<XElementResolver<string>>() 
     .FromMember(source => source.Element("text"))) 

Nó có thể trông phức tạp lúc đầu, nhưng tất cả những gì thực sự xảy ra ở đây là chúng ta đang cung cấp chi tiết để AutoMapper vào những gì giá trị sử dụng trong đối tượng nguồn của tôi và cách ánh xạ nó tới thuộc tính của đối tượng đích. Có một dòng cụ thể tôi muốn tập trung vào trong các bản đồ thực địa Body trên:

options => options.ResolveUsing<XElementResolver<ulong>>() 
        .FromMember(source => source.Element("id"))) 

Các XElementResolver là một resolver giá trị tùy chỉnh (http://automapper.codeplex.com/wikipage?title=Custom%20Value%20Resolvers) mà Seth đã đưa ra để xử lý phân tích các đối tượng nguồn XmlElement để lấy một giá trị mạnh mẽ để sử dụng trong ánh xạ. Tôi sẽ chi tiết hơn rằng trong một khoảnh khắc, nhưng trước khi chúng ta di chuyển trên hãy nhìn vào bản đồ đầy đủ của tôi:

Mapper.CreateMap<XElement, ITweetContract>() 
.ForMember(
    dest => dest.Id, 
    options => options.ResolveUsing<XElementResolver<ulong>>() 
     .FromMember(source => source.Element("id"))) 
.ForMember(
    dest => dest.Name, 
    options => options.ResolveUsing<XElementResolver<string>>() 
     .FromMember(source => source.Element("user") 
      .Descendants("name").Single())) 
.ForMember(
    dest => dest.UserName, 
    options => options.ResolveUsing<XElementResolver<string>>() 
     .FromMember(source => source.Element("user") 
      .Descendants("screen_name").Single())) 
.ForMember(
    dest => dest.Body, 
    options => options.ResolveUsing<XElementResolver<string>>() 
     .FromMember(source => source.Element("text"))) 
.ForMember(
    dest => dest.ProfileImageUrl, 
    options => options.ResolveUsing<XElementResolver<string>>() 
     .FromMember(source => source.Element("user") 
      .Descendants("profile_image_url").Single())) 
.ForMember(
    dest => dest.Created, 
    options => options.ResolveUsing<XElementResolver<string>>() 
     .FromMember(source => source.Element("created_at"))); 
  1. Các Generic XElementResolver

tùy chỉnh này trình phân giải giá trị là khóa thực sự cho phép các bản đồ này có thể hoạt động trong giải pháp gốc. Tôi đã sử dụng lại trình phân giải này trong ví dụ này như chúng ta đã thấy ở trên. Đây là tất cả những gì là cần thiết để tạo ra các lớp tùy chỉnh phân giải:

public class XElementResolver<T> : ValueResolver<XElement, T> 
{ 
protected override T ResolveCore(XElement source) 
{ 
    if (source == null || string.IsNullOrEmpty(source.Value)) 
     return default(T); 
    return (T)Convert.ChangeType(source.Value, typeof(T)); 
} 
} 

XElementResolver generic này cho phép sử dụng dễ dàng vượt qua các loại giá trị lấy ra trong bản đồ của chúng tôi ở trên. Ví dụ, cú pháp sau đây được sử dụng để gõ mạnh giá trị lấy từ XmlElement trong .ForMember lĩnh vực của Id() tuyên bố trên:

ResolveUsing<XElementResolver<ulong>>() 

Với bản đồ của tôi hoàn toàn cấu hình và khởi tạo, tôi đã sẵn sàng để gọi API Twitter và tận dụng AutoMapper để hiển thị Dòng thời gian công khai mới nhất.

  1. Đưa miếng Cùng

Tôi tạo ra một lớp đơn giản trách nhiệm thu hồi đáp Twitter API:

public class TwitterTimelineRetriever 
{ 
private readonly XDocument _twitterTimelineXml; 
public TwitterTimelineRetriever() 
{ 
    _twitterTimelineXml = XDocument 
     .Load("http://api.twitter.com/1/statuses/public_timeline.xml"); 
} 
public IEnumerable<ITweetContract> GetPublicTimeline(int numberOfTweets) 
{ 
    var tweets = _twitterTimelineXml.Descendants("status") 
     .Take(numberOfTweets); 
    return tweets.Select(Mapper.Map<XElement, ITweetContract>).ToList(); 
} 
} 

Phương pháp GetPublicTimeline là một phương pháp đơn giản quay trở lại, bạn đã đoán, Lịch trình công khai của Twitter bằng cách tận dụng bản đồ mà chúng tôi đã tạo trước đó:

return tweets.Select(Mapper.Map<XElement, ITweetContract>).ToList(); 

Trong HomeController trang web MVC3 của tôi, tôi có thể thực hiện cuộc gọi nhanh chóng với phương pháp thu hồi, đề nghị 10 kết quả cuối cùng:

public class HomeController : Controller 
{ 
private TwitterTimelineRetriever _twitterTimelineRetriever; 
public ActionResult Index() 
{ 
    _twitterTimelineRetriever = new TwitterTimelineRetriever(); 
    ViewModel.Message = "Twitter Public Timeline"; 
    return View(_twitterTimelineRetriever.GetPublicTimeline(10)); 
} 
} 

Và cuối cùng, sau một định dạng nhỏ trong quan điểm của tôi bằng cách sử dụng công cụ xem Razor mới từ Microsoft, tôi có hiển thị dòng thời gian công khai của tôi!

+6

Làm thế nào để sử dụng AutoMapper như thế này nữa "tự động" sau đó tự sử dụng XML ngay vào POCO? – user2864740

7

Bạn cần phải kiểm tra XML serialization in .NET cho điều này - đó là cách để sắp xếp một đối tượng vào XML hoặc deserialize nó từ XML.

Tự động hóa có thể được sử dụng để đặt thuộc tính giữa hai đối tượng - nó không xử lý XML chút nào.

Tài nguyên khác:

4

Cuối ngày, nhưng ai đó đã sử dụng AutoMapper để ánh xạ XML tới POCO thay vì đi xuống tuyến đường XMLSerialization. Tôi đã tìm thấy mục nhập blog sau: - Simplify Using Xml Data with AutoMapper and Linq-to-Xml

Điều này là đủ để bạn bắt đầu triển khai trình giải quyết tùy chỉnh chung của riêng bạn nếu ví dụ không đủ.

EDIT: cố định liên kết EDIT: thực sự cố định liên kết

+0

ricardo - mục nhập blog đó rất hữu ích. cảm ơn!! –

+1

Liên kết đó hiện đã bị hỏng. Đây là một trong những làm việc: http://dannydouglass.com/blog/2010/11/06/simplify-using-xml-data-with-automapper-and-linqtoxml/ – GFoley83

+1

@ GFoley83 liên kết của bạn bây giờ đã bị phá vỡ quá! –

Các vấn đề liên quan