使用快速简便的可保存对象类、JSON 和 LINQ 的简单博客






2.78/5 (3投票s)
学习如何创建自动保存和检索其数据的类(),以及如何使用 LINQ 快速查询这些数据。我的类 `Saveable` 的示例实现展示了创建博客是多么容易。

引言
你是否曾经创建了一个出色的类,然后不得不编写子例程来保存和检索它?太痛苦了。我对此感到厌倦,所以创建了 `Saveable` 类。你可以通过继承来扩展任何你编写的类。
它使用 JSON(JavaScript 对象表示法)序列化(现在内置于 .NET Framework 3.5 和 Visual Studio 2008 中)来迭代类的成员,检索数据并将其保存到文件中。
等等!?你用 JSON 作为数据库!? 是的,没错。JSON 序列化比 XML 序列化更快,创建的文件更小,同时仍然保持人类可读性。我知道这并非 JSON 的原始目的,但它有效,而且效果非常好。
我包含的示例实现是一个博客引擎。警告:它非常简单,只是为了展示 `Saveable(Of T)` 的特性。在将其投入实际使用之前,它需要进行大量的改进。但它包含用于管理帖子和评论的代码。它还包含使用 `RegularExpression` 和 `LINQ` 对帖子执行排序搜索的代码。
Using the Code
我的 `Saveable` 类的核心是两个方法:`ToJSON` 和 `FromJSON`
Shared Serializer As New Runtime.Serialization.Json.DataContractJsonSerializer(GetType(T))
Public Shared Function ToJSON(ByVal Obj As Object) As String
Dim tt As New IO.MemoryStream
Serializer.WriteObject(tt, Obj)
tt.Close()
Return System.Text.Encoding.ASCII.GetString(tt.ToArray)
End Function
Public Shared Function FromJSON(ByVal Data As String, ByVal Type As Type) As Object
If String.IsNullOrEmpty(Data) Then Return Nothing
Dim tt As New IO.MemoryStream(System.Text.Encoding.ASCII.GetBytes(Data))
Return Serializer.ReadObject(tt)
End Function
这些方法将你的对象转换为和从文本转换。
要开始使用该类,请创建你自己的类,该类继承自 `Saveable(Of T)`,其中 `T` 是你的类的类型。然后导入 `System.Runtime.Serialization` 并添加 `DataContract` 属性。
Imports System.Runtime.Serialization
Public Class BlogMessage : Inherits Saveable(Of BlogMessage)
End Class
接下来,添加你的类需要的任何属性。`Saveable(Of T)` 类已经包含用于 `ID as GUID`、`DateCreated as Date` 和 `DateModified as Date` 的属性。
Imports System.Runtime.Serialization
<DataContract()> Public Class BlogMessage : Inherits Saveable(Of BlogMessage)
Dim _Title As String
<DataMember()> Public Property Title() As String
Get
Return _Title
End Get
Set(ByVal value As String)
_Title = value
End Set
End Property
Dim _message As String
<DataMember()> Public Property Message() As String
Get
Return _message
End Get
Set(ByVal value As String)
_message = value
End Set
End Property
End Class
现在,你可以做一些很酷的事情了
'Create a New One
Dim b as New BlogMessage With { .Title = "My New Post!", _
.Message = "This is the content for the post." }
b.Save()
`Save()` 方法会在必要时创建一个新的 `ID`,如果为空则设置 `DateCreated`,更新 `DateUpdated`,将对象序列化为文本,并将其保存到以 ID 命名的 *.js 文件中——位于以对象命名的文件夹下(在本例中为 `BlogMessage`)在 *App_Data* 文件夹下(即 *~/App_Data/BlogMessage/42dc0fb5-c516-4536-b273-6bbff8ed33ae.js*)。
将对象加载回内存同样容易
'Load an Old One
Dim b as BlogMessage = BlogMessage.Load("42dc0fb5-c516-4536-b273-6bbff8ed33ae")
'Now do something with it
Response.Write(b.Message)
现在,将你的类提升到一个新的水平。我添加了另一个类 `BlogComment`,它也继承自 `Saveable(Of T)`。然后我添加了一些 LINQ(顺便说一句,它真的太棒了)
Imports System.Runtime.Serialization
Imports System.Linq
<DataContract()> Public Class BlogMessage : Inherits Saveable(Of BlogMessage)
<DataMember(Name:="Comments")> Dim _comments As Generic.Dictionary_
(Of Guid, BlogComment)
Public ReadOnly Property Comments() As Generic.Dictionary(Of Guid, BlogComment)
Get
If _comments Is Nothing Then _comments = _
New Generic.Dictionary(Of Guid, BlogComment)
Return _comments
End Get
End Property
Dim _Title As String
<DataMember()> Public Property Title() As String
Get
Return _Title
End Get
Set(ByVal value As String)
_Title = value
End Set
End Property
Dim _message As String
<DataMember()> Public Property Message() As String
Get
Return _message
End Get
Set(ByVal value As String)
_message = value
End Set
End Property
Public Shared Function GetPostByTitle(ByVal Title As String) As BlogMessage
Dim o As Generic.IEnumerable(Of BlogMessage) = From b As BlogMessage In _
BlogMessage.GetAll Where b.Title.Equals_
(Title, StringComparison.OrdinalIgnoreCase) Take 1
If o.Count = 0 Then Return Nothing
Return o.First
End Function
Public Shared Function Search(ByVal Terms As String) As BlogMessage()
Dim r As New Regex("(" & Terms.Trim.Replace(" ", ")|(") & ")", _
RegexOptions.Singleline Or RegexOptions.IgnoreCase Or _
RegexOptions.Compiled)
Return (From b As BlogMessage In BlogMessage.GetAll Select b, k = _
b.Rank(r) Where k >= 0 Order By k Descending Select b).ToArray
End Function
Private Function Rank(ByVal r As Regex) As Double
Dim c As String = Title & vbNewLine & Message
Dim m As MatchCollection = r.Matches(c)
If m.Count = 0 Then Return -1
Return Aggregate dm As Match In m Into Sum(dm.Index / c.Length)
End Function
End Class
关注点
JSON 和 LINQ 很酷!
待办事项:学习更多 LINQ!它很棒,而且功能强大。请查看这里的示例 here。