行動裝置網路環境多變,應用程式需能感知連線狀態、頻寬成本與資料用量;同時,資料序列化是與雲端服務溝通的核心技能。本文涵蓋 Windows.Networking.Connectivity 網路資訊查詢,以及 JSON、XML、RSS/Atom 三種主流序列化格式的處理技巧。
ConnectionProfile profile = NetworkInformation.GetInternetConnectionProfile();
if (profile != null) {
// 連線設定檔名稱
string name = profile.ProfileName;
// 連線等級:None, LocalAccess, ConstrainedInternetAccess, InternetAccess
NetworkConnectivityLevel level = profile.GetNetworkConnectivityLevel();
// 網路介面卡資訊
NetworkAdapter adapter = profile.NetworkAdapter;
if (adapter != null) {
Guid id = adapter.NetworkAdapterId;
ulong inbound = adapter.InboundMaxBitsPerSecond; // 最大入站速率 bps
ulong outbound = adapter.OutboundMaxBitsPerSecond; // 最大出站速率 bps
}
// 最近 1 小時資料用量
DataUsage usage = profile.GetLocalUsage(DateTime.Now.AddHours(-1), DateTime.Now);
ulong sent = usage.BytesSent;
ulong received = usage.BytesReceived;
// 連線成本與資料方案
ConnectionCost cost = profile.GetConnectionCost();
DataPlanStatus plan = profile.GetDataPlanStatus();
}
// 監聽網路狀態變更
NetworkInformation.NetworkStatusChanged += (sender) => { /* 更新 UI */ };
[DataContract(Name="product")]
public class Product : INotifyPropertyChanged {
[DataMember(Name="productId", IsRequired=true, Order=1)]
public int ProductId { get; set; }
[DataMember(Name="name", IsRequired=true, Order=2)]
public string Name { get; set; }
public decimal Price { get; set; }
[DataMember(Name="createTime", IsRequired=true, Order=3)]
public DateTime CreateTime { get; set; }
// INotifyPropertyChanged 實作略
}
// 序列化
var settings = new DataContractJsonSerializerSettings { DateTimeFormat = new DateTimeFormat("yyyy-MM-dd HH:mm:ss") };
var serializer = new DataContractJsonSerializer(typeof(List), settings);
using (var ms = new MemoryStream()) {
serializer.WriteObject(ms, products);
string json = Encoding.UTF8.GetString(ms.ToArray(), 0, (int)ms.Length);
}
// 反序列化
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(json))) {
var list = serializer.ReadObject(ms) as List;
}
無需完整反序列化為物件圖,直接操作 JsonObject / JsonArray:
JsonArray array = JsonArray.Parse(jsonString);
JsonObject first = array[0].GetObject();
string name = first["name"].GetString();
var serializer = new DataContractSerializer(typeof(List), "root", "");
using (var ms = new MemoryStream()) {
serializer.WriteObject(ms, products);
string xml = Encoding.UTF8.GetString(ms.ToArray());
}
自訂 XmlWriter 覆寫 WriteStartElement、WriteStartAttribute 等方法,攔截並移除 https://schemas.datacontract.org 等預設命名空間,產生乾淨 XML:
public class MyXmlWriter : XmlWriter {
private XmlWriter _writer;
private bool _ignoreEndAttrCall;
public override void WriteStartElement(string prefix, string localName, string ns) {
if (ns != null && ns.StartsWith("https://schemas.datacontract.org")) ns = null;
_writer.WriteStartElement(prefix, localName, ns);
}
// 其他覆寫方法略...
}
使用方式:
XmlWriter xmlWriter = MyXmlWriter.Create(ms, settings);
serializer.WriteObject(new MyXmlWriter(xmlWriter), products);
XDocument doc = XDocument.Parse(xmlWithoutPreamble);
var products = from p in doc.Root.Elements("product")
select new Product {
ProductId = int.Parse(p.Element("productId").Value),
Name = p.Element("name").Value
};
注意:XML 字串不可包含 UTF-8 Preamble (EF BB BF),否則 XDocument.Parse 會失敗,需先移除。
SyndicationClient client = new SyndicationClient();
client.BypassCacheOnRetrieve = true;
client.SetRequestHeader("User-Agent", "Mozilla/5.0 ...");
SyndicationFeed feed = await client.RetrieveFeedAsync(new Uri("https://feed.cnblogs.com/blog/u/18098/rss"));
foreach (SyndicationItem item in feed.Items) {
string title = item.Title.Text;
// 可進一步存取 Links, Summary, PublishDate 等
}
catch (Exception ex) {
SyndicationErrorStatus status = SyndicationError.GetStatus(ex.HResult);
// 處理 status: NotFound, ServerError, InvalidXml 等
}
掌握網路資訊查詢讓應用程式具備連線感知能力;熟練 JSON/XML/RSS 序列化技術則是串接雲端服務、解析開放資料的基石。選擇適合的工具:DataContractJsonSerializer 適合強型別雙向序列化,JsonObject 適合動態解析,XLINQ 則是 XML 處理的瑞士刀。