(Post 12/06/2007) Đa phần ứng dụng thực tế
đều có nhu cầu lưu trữ và truy xuất thông tin cấu hình hệ thống. Người
ta thường lưu trữ các thông tin này trong tập tin *.ini hoặc trong một
dạng tập tin có cấu trúc do người phát triển ứng dụng quy định. Trong
ứng dụng viết trên nền .NET, thông tin về cấu hình được chứa trong tập
tin App.Config (dùng cho Windows Application) và Web.Config (dùng cho
ASP.NET Web Application) dựa trên định dạng XML. Để đơn giản, tôi sẽ gọi
đây là tập tin cấu hình.
Mối liên
hệ giữa configuration section, configuration declaration (section)
và configuration settings (tags) |
|
Tập Tin Cấu Hình
Tập tin cấu hình là một tập tin dạng văn bản (text),
dựa trên chuẩn XML. Tập tin này được chia thành nhiều phần khác nhau,
gọi là configuration section, cho phép đặt thông tin cấu hình cho từng
phần khác nhau của ứng dụng như Debugging, Profiling, Security,... Trong
phạm vi bài viết này, chúng ta chỉ quan tâm đến phần thông tin cấu hình
cho phép chúng ta, với vai trò là người phát triển ứng dụng, có thể đưa
thông tin vào tập tin này và truy xuất thông tin lúc chương trình thực
thi.
Mỗi phần thông tin cấu hình đưa vào tập tin cấu hình
sẽ gồm 2 phần:
- Phần khai báo (configuration declaration): quy định lớp đối tượng
(section handler) nào sẽ đảm nhận việc đọc thông tin từ configuration
settings tương ứng.
- Phần dữ liệu thực sự (configuration settings): chứa cấu trúc dữ
liệu mà ta muốn thêm vào tập tin cấu hình.
Đối với Windows Application, tập tin cấu hình thường
nằm trong cùng thư mục với chương trình và những thông tin cấu hình này
sẽ ảnh hưởng đến toàn bộ hoạt động của chương trình. Tuy nhiên, khi bạn
cài đặt .NET Framework, còn có một tập tin cấu hình ảnh hưởng đến tất
cả các ứng dụng chạy trên máy. Bạn có thể tìm thấy tập tin này trong thư
mục cài đặt .NET Framework tại $WINDIR\Microsoft.NET\Framework\v1.1.4322\CONFIG\machine.config.
Lúc thực thi, ứng dụng sẽ ưu tiên đọc thông tin cấu hình
trong tập tin machine.config trước, sau đó mới tới tập tin cấu hình. Dựa
trên thông tin trong configuration section, kết quả thông tin cấu hình
sau cùng sẽ là:
- Kết hợp tập tin machine.config và tập tin cấu hình.
- Thông tin cấu hình ở tập tin cấu hình chiếm độ ưu tiên.
Thông Tin Cấu Hình
.NET cung cấp sẵn một configuration section gọi là appSettings.
Phần này được khai báo trong tập tin machine.config như sau:
Phần configuration declaration trong tập tin machine.config
<section name="appSettings"
type="System.Configuration.NameValueFileSectionHandler,
System, Version=1.0.5000.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089"/>
Phần configuration settings sẽ được đặt lồng trong appSettings.
Thông tin này được đặt trong tập tin App.Config hoặc Web.Config.
<appSettings>
<add key="author" value="Ngô Đình
Nghĩa"/>
<add key="article" value="Thiết
Lập Cấu Hình Cho Ứng Dụng .NET"/>
</appSettings>
Mặc dù .NET cung cấp phần chứa thông tin ở dạng Key-Value
trong <appSettings> như bạn thấy ở trên, nhưng phần này chỉ thích
hợp nếu như bạn có một vài cặp Key-Value. Tuy nhiên, nếu ứng dụng của
bạn có nhiều thông tin trong <appSettings> sẽ dẫn đến việc khó tổ
chức thông tin cấu hình theo một dạng cấu trúc nào đó. Vì vậy, .NET cho
phép bạn có thể định nghĩa phần thông tin cấu hình riêng theo ý mình.
.NET cho phép định nghĩa configuration section trong
một thẻ XML theo cấu trúc sau:
<configSections>
<section name="sampleSection"
type="System.Configuration.SingleTagSectionHandler"
/>
</configSections>
Như trình bày ở trên, mỗi configuration section sẽ bao
gồm 2 phần declaration và settings. Phần declaration tương ứng với thẻ
<section> ở trên chứa 2 thuộc tính:
- name: thuộc tính này chứa tên của thẻ trong phần configuration
settings mà section handler sẽ đọc thông tin từ đó.
- type: thuộc tính này chứa tên của lớp (còn gọi là section handler)
phụ trách việc đọc thông tin từ trong configuration settings.
Phần khai báo chỉ ra rằng thông tin trong phần configuration
settings sẽ được đọc thông qua System.Configuration.NameValueFileSectionHandler
section handler.
.NET cung cấp sẵn một số lớp trong System.Configuration
mà ta có thể dùng để khai báo cho thuộc tính type ở trên.
Chúng ta cũng có thể dùng thẻ <sectionGroup> được
.NET cung cấp để thêm nhiều thông tin chi tiết vào trong phần khai báo:
<configSections>
<sectionGroup name="DatabaseSettings">
<sectionGroup name="ConnectionSettings">
<section .../>
...
...
</sectionGroup>
</sectionGroup>
...
...
</configSections>
Truy xuất cấu hình
Giả sử rằng bạn có một configuration settings chứa thông
tin cấu hình dạng cặp Key-Value như sau:
<!--// configuration settings -->
<siteSettings>
<common>
<emails>
<add key="adminmail"
value="[email protected]"/>
<add key="salesmail"
value="[email protected]"/>
<add key="supportmail"
value="[email protected]"/>
<add key="admail"
value="[email protected]"/>
</emails>
</common>
</siteSettings>
Bây giờ, điều bạn cần làm là cho ứng dụng biết phần configuration
settings này sẽ được xử lý như thế nào. .NET cung cấp sẵn một section
handler gọi là NameValueSectionHandler nằm trong System.Configuration
có nhiệm vụ xử lý các section chứa thông tin ở dạng cặp Key-Value. Chúng
ta sẽ dùng section handler này xử lý section mà chúng ta vừa định nghĩa
ở trên.
<!--// configuration declaration -->
<configuration>
<configSections>
<sectionGroup name="siteSettings">
<sectionGroup name="common">
<section name="emails"
type="System.Configuration.NameValueSectionHandler,
System"/>
</sectionGroup>
</sectionGroup>
</configSections>
...
</configuration>
Một khi đã đặt configuration settings and configuration
declaration vào trong tập tin cấu hình, bạn có thể truy xuất thông tin
đó từ trong ứng dụng như sau:
...
NameValueCollection nvc = (NameValueCollection)
ConfigurationSettings.GetConfig("siteSettings/common/emails");
Label1.Text = nvc["salesmail"];
Label2.Text = nvc["supportmail"];
Label3.Text = nvc["adminmail"];
...
Một ví dụ thứ hai về cách dùng SingleTagSectionHandler.
Giả sử bạn đưa thông tin vào tập tin cấu hình với cấu trúc như sau:
<configuration>
<sampleSection setting1="value one"
setting2="value two" setting3="third value" />
</configuration>
Bạn có thể thêm configuration declaration như sau:
<configuration>
<configSections>
<section name="sampleSection"
type="System.Configuration.SingleTagSectionHandler"
/>
</configSections>
</configuration>
Trong ứng dụng, bạn có thể dùng đoạn code sau để truy
xuất thông tin:
using System;
using System.Collections;
using System.Configuration;
public class MyConfigurationReader
{
public void ReadMySettings()
{
IDictionary sampleTable;
string value1;
string value2;
string value3;
sampleTable = (IDictionary) ConfigurationSettings.GetConfig("sampleSection");
value1 = sampleTable("setting1").ToString();
value2 = sampleTable("setting2").ToString();
value3 = sampleTable("setting3").ToString();
}
}
Để khai báo một section handler, bạn phải tạo ra một lớp
đối tượng cài đặt giao diện System.Configuration.IconfigurationSectionHandler.
public class MyConfigHandler: IconfigurationSectionHandler
{
...
}
Có một method mà bạn phải định nghĩa khi cài đặt giao
diện IconfigurationSectionHandler:
object Create (object parent, object configContext,
XmlNode section)
- parent - configuration settings mà là cha của configuration section.
- configContext - một biến kiểu HttpConfigurationContext, khi hàm
Create được gọi từ ASP.NET configuration system. Bằng không, tham
số này sẽ được gán giá trị là null (C#) hoặc Nothing (VB.NET).
- section - XmlNode bao gồm thông tin cấu hình. Tham số này cho phép
truy cập trực tiếp đến nội dung XML của configuration section.
- Giá trị trả về - Hàm này trả về một lớp đối tượng do bạn quy định.
Dưới đây là một ví dụ về việc khai báo lớp SectionHandler
để đọc thông tin cấu hình theo cấu trúc bạn quy định:
namespace ConfigSectionProj
{
public class DatabaseInfoConfigHandler: IConfigurationSectionHandler
{
public DatabaseInfoConfigHandler(){}
public object Create(object parent, object configContext,
System.Xml.XmlNode section)
{
DatabaseInfo objDB = new DatabaseInfo();
objDB.Server = section.SelectSingleNode("server").InnerText;
objDB.Database = section.SelectSingleNode("database").InnerText;
objDB.User = section.SelectSingleNode("user").InnerText;
objDB.Password = section.SelectSingleNode("password").InnerText;
return objDB;
}
}
}// end namespace
DatabaseInfo là lớp đối tượng dùng để định nghĩa cấu
trúc của configuration section. Lớp này chứa các phần tử tương ứng với
các thông tin trong configuration settings.
// declare DatabaseInfo class
namespace ConfigSectionProj
{
public class DatabaseInfo
{
// public members
public string Server = string.Empty;
public string Database = string.Empty;
public string User = string.Empty;
public string Password = string.Empty;
// constructor
public DatabaseInfo(){}
}
}// end namespace
Sau khi tạo xong lớp section handler cho configuration
section, bạn có thể khai báo section này trong tập tin cấu hình như sau:
<!--// configuration declaration -->
<configSections>
...
<sectionGroup name="databaseProviderInfo">
<section name="databaseInfo"
type="ConfigSectionProj.DatabaseInfoConfigHandler,ConfigSectionProj"/>
</sectionGroup>
...
</configSections>
Trong đó, ConfigSectionProj là tên của namespace.
Sau đó bạn có thể khai báo phần configuration settings
trong tập tin cấu hình như sau:
<!--// configuration settings -->
<databaseProviderInfo>
<DatabaseInfo>
<database>Northwind</database>
<server>localhost</server>
<user>testuser</user>
<password>testpassword</password>
</DatabaseInfo>
</databaseProviderInfo>
Để đọc section databaseInfo từ trong tập tin App.config
hoặc Web.Config, bạn có thể dùng hàm ConfigurationSettings.GetConfig
với cú pháp như sau:
DatabaseInfo obj = (DatabaseInfo)ConfigurationSettings.GetConfig("databaseProviderInfo/databaseInfo");
Hàm ConfigurationSettings.GetConfig sẽ trả về
một lớp đối tượng cho configuration section mà bạn đã định nghĩa.
Lời Kết
Hầu hết các ứng dụng đều có nhu cầu chứa thông tin chung
cho toàn bộ ứng dụng ở một nơi lưu trữ nào đó, có thể là trong tập tin
ini hay registry. Việc lựa chọn cách thức lưu thông tin ở đâu là tùy thuộc
vào người phát triển ứng dụng và ngữ cảnh mà ứng dụng sẽ hoạt động. Thực
tế sẽ thuận lợi hơn rất nhiều nếu chúng ta tận dụng được những khả năng
mà hệ thống hỗ trợ. Hy vọng qua bài báo này, các bạn phần nào nắm được
cách thức thêm thông tin cấu hình vào cho ứng dụng của mình thông qua
tập tin cấu hình mà .NET Framework hỗ trợ.
Tên trường
|
Mô tả |
NameValueSectionHandler |
Đọc thông tin cấu hình ở dạng một cặp Name-Value được trả về thông
qua lớp đối tượng
System.Collections.Specialized.NameValueCollection |
DictionarySectionHandler |
Đọc thông tin cấu hình ở dạng một cặp Key-Value được trả về thông
qua lớp đối tượng System.Collections.Hashtable |
SingleTagSectionHandler |
Đọc thông tin cấu hình ở dạng một cặp Key-Value và trả về thông
qua lớp đối tượng System.Collections.Hashtable |
IgnoreSectionHandler |
cung cấp một section handler định nghĩa cho configuration section
được truy xuất và xử lý bởi hệ thống khác hơn là dùng System.Configuration.
Để truy cập thông tin trong phần này, chúng ta phải đọc và duyệt
qua toàn bộ thẻ XML trong tập tin cấu hình |
User-defined Section handlers |
do người dùng định nghĩa bằng cách cài đặt giao diện
System.Configuration.IConfigurationSectionHandler |
Ngô Đình Nghĩa
Global CyberSoft Vietnam
(theo PC World VN) |