Serializationtrong.NET
Serialization là một quá trình chuyển đối tượng (object) sang một hình
thức khác, để sử dụng khi lưu trữ hoặc chuyển dữ liệu qua mạng. Bài viết
này đề cập đến việc chuyển đối tượng sang dạng XML.
XMLSerializer
.Net Framework cung cấp các lớp trong namespace System.XML.Serialization cho công việc
chuyển đổi này, trong đó lớp XMLSerializer có vai trò quan trọng. Mỗi thể hiện (instance) của
lớp này được tạo ra cho mỗi đối tượng cần chuyển. Nó chứ
a các thông số ánh xạ để chuyển
thuận hoặc chuyển ngược giữa đối tượng và dữ liệu XML. Lớp XMLSerializer có 2 phương thức
quan trọng:
public void Serialize(Stream, object);
public object Deserialize(Stream);
Chúng ta có thể sử dụng lớp XMLSerializer như sau:
XMLSerializer serializer = new XMLSerializer(typeof(OrderedItem));
OrderedItem order = new OrderedItem();
//chuyển thuận
XMLWriter writer = new XMLTextWriter(fs, new UTF8Encoding());
serializer.Serialize(writer, order);
//chuyển ngược
fs = new FileStream(ten_file, FileMode.Open);
XMLReader reader = new XMLTextReader(fs);
i = (OrderedItem) serializer.Deserialize(reader);
Mặc định XMLSerializer sẽ chuyển tất cả các trường (field) public, các thuộc tính (Property)
read/write và các giá trị khác null trở thành element với tagname là tên thuộc tính. Tất cả các
element này được
đặt trong lớp element cha, với tagname là tên lớp. Ví dụ lớp Person được trình
bày như dưới đây:
public class Person
{
public string Name = "Ten";
public int Age = 33;
private string Address = "HCM";
public string Sex = null;
public Person() { }
}
sẽ được chuyển thành dữ liệu XML:
<?XML version="1.0"?>
<Person XMLns:xsd="http://www.w3.org/2001/XMLSchema"
XMLns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Name>Ten</Name>
<Age>33</Age>
</Person>
Address không được chuyển vì nó là thuộc tính private, và Sex cũng không có trong dữ liệu
XML vì có giá trị null.
XMLSerializer có đầy đủ các chức năng để thực hiện việc chuyển các đối tượng sang dữ liệu
XML và ngược lại. Sau đây, chúng ta sẽ khảo sát các khai báo cần thiết để chuyển các thuộc tính
của một đối tượng sang dữ liệu XML.
Chuyển các đối tượng
Nếu bạn muốn chuyển lớp Person thành element với tagname là Employee thay vì Person, bạn
định nghĩa nó thông qua thuộc tính XMLRoot:
[XMLRoot("Employee")]
public class Person
{ }
Nếu muốn chuyển thuộc tính Name thành element có TagName là PersonName, bạn định nghĩa
nó thông qua XMLElement:
[XMLElement("PersonName")]
public string Name = "Ten";
// tương tự thuộc tính Age thành element PersonAge
[XMLAttribute("PersonAge")]
public int Age = 33;
Nếu không muốn chuyển một thuộc tính dạng public sang dữ liệu XML, ta dùng XMLIgnore:
[XMLIgnore()]
public string Sex = "Nam";
Nếu các thuộc tính có kiểu là một lớp, các thành phần public của lớp được chuyển như đã định
nghĩa, và element tương ứng của lớp sẽ có tagname được định nghĩa trong XMLElement.
Lớp Person được chỉ định bởi:
[XMLElement("Supervisor")]
public Person Supervisor = null;
sẽ được chuyển thành dữ liệu XML như sau:
<Supervisor>
<PersonName>Ten</PersonName>
</Supervisor>
XMLIgnore có thể giúp chúng ta chuyển hoặc không chuyển sang XML một trường hoặc thuộc
tính tùy thuộc vào giá trị của nó.
Để thực hiện việc này, chúng ta thêm một thuộc tính mới vào lớp với tên trùng với thuộc tính
cộng thêm từ Specified sau đó. Ví dụ, chúng ta không muốn chuyển thuộc tính Age của lớp
Person, chúng ta thực hiện như sau:
[XMLAttribute("PersonAge")]
public int Age = 33;
[XMLIgnore()]
public bool AgeSpecified = false;
Nếu AgeSpecified có giá trị là true, Age sẽ được chuyển. Khi làm việc trên XMLSerializer tôi
rất thích đặc điểm này vì nó giúp chúng ta bật tắt việc chuyển theo giá trị.
Chuyển mảng, danh sách,
Ở phần trên chúng ta đã lần lượt xem xét các khai báo XML để chuyển các đối tượng đơn, trong
phần này chúng ta sẽ khảo sát các khai báo cho các đối tượng tập hợp (Collection).
Tương tự như ở phần trên, chúng ta cũng phải chuyển các đối tượng ở dạ
ng mảng vào thành một
element.
[XMLArray("Agents")]
[XMLArrayItem("Agent", typeof(Person))]
public ArrayList Agents = null;
Kết quả khi chuyển sẽ là:
<Employee>
<PersonName>Ten</PersonName>
<Agents>
<Agent>
<PersonName>Ten</PersonName>
</Agent>
</Agents>
</Employee>
Ở ví dụ trên, các phần tử có kiểu là Person, đều được chuyển thành các element Agent. Nếu
muốn thêm các kiểu khác vào danh sách, chúng ta thêm các khai báo XMLArayItem tương ứng
tiếp sau khai báo cho Person.
Nếu muốn tất cả các phần tử trong danh sách đều có tagname giống nhau, chúng ta cần khai báo
XMLArrayItem với một tham số là ElementName (bỏ qua kiểu dữ liệu).
Kết quả chúng ta có tập tin dữ liệu XML như sau:
<Employee >
<PersonName>Name</PersonName>
<Agents>
<Agent xsi:type="Person">
<PersonName>Ten</PersonName>
</Agent>
<Agent xsi:type="Person1" />
</Agents>
</Employee>
Thuộc tính xsi:type được thêm vào cho các element của ArrayList để giúp việc chuyển ngược
dữ liệu XML này sang đối tượng.
Trên đây tôi đã trình bày sơ lược về XMLSerializer. Nếu làm việc với đối tượng này, bạn sẽ phát
hiện nhiều điều đặc biệt hơn nữa và hy vọng bạn sẽ thích thú. .NET Framework cũng cho phép
bạn lấy các khai báo cho các lớp để chuyển thông qua viết lệnh. Nếu bạn đã từng sử dụng
namespace System.Reflection trong .NET, hay reflection trong Java, chắc là sẽ cảm thấy thích
thú với đặc đ
iểm này.
XMLSerializer có một hạn chế khi dự án có số lượng lớp quá lớn. Khi đó, việc tạo thể hiện cho
hàng trăm lớp có khả năng làm chậm hệ thống. Tuy XMLSerializer cho phép bạn khai báo để nó
chỉ tìm kiếm các đối tượng trong một số lớp cho trước, nhưng nó khá chậm. Theo kinh nghiệm
của tôi khi làm việc trên dự án lớn, bạn chỉ nên tạo một thể hiện của XMLSerializer cho mỗi lớp
và dùng nó xuyên suốt toàn bộ ứng dụng thì vấn đề tốc độ thực thi sẽ được giải quyết.
. Serialization trong .NET
Serialization là một quá trình chuyển đối tượng (object) sang một hình
thức khác, để sử dụng khi lưu trữ hoặc chuyển dữ liệu. XML.
XMLSerializer
.Net Framework cung cấp các lớp trong namespace System.XML .Serialization cho công việc
chuyển đổi này, trong đó lớp XMLSerializer