使用泛型和委托的 JSON 和 C#






4.33/5 (2投票s)
使用泛型和委托的 JSON 和 C#
JSON,或 JavaScript 对象表示法,是一种用于传输数据的方法,类似于 XML 和其他格式。 使用此方法有很多优点。 它是人类可读的,并且可以轻松地转换为浏览器客户端的对象。
使用 JSON,我可以这样声明一个数组
var myArray = ["this","that","the other"];
对象表示法甚至更简单。 想象一个 C# "Person
" 类
public class Person
{
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string SSN { get; set; }
}
如果我想将此数据传递给客户端,我可以这样做
var person = {
"ID" : "1",
"FirstName" : "Jeremy",
"LastName" : "Likness",
"SSN" : "111-222-3333"
};
alert("My name is " + person.FirstName + " " + person.LastName);
WebForms 视图引擎(你们大多数人在 .NET 中使用的引擎......虽然像 NVelocity 这样的其他视图引擎已经作为 MonoRail 项目的一部分存在,但 Microsoft 最近才发布 MVC 候选版本,该版本引入了 Model-View-Controller 视图引擎)的一个缺点是,它在呈现简单标签时会给客户端带来过重的负担。 如果你比较过 <input type="text">
和 <asp:TextBox>
,你就会明白我的意思。
此外,开发人员往往沉迷于 AJAX 框架的“便捷性”,而常常忽略了在更新面板中包装级联下拉列表的性能影响。 一种更简单的方法是序列化这些值,并使用像 JQuery 这样的第三方工具绑定它们。
在开发此框架时,我意识到将我的领域对象序列化为 JSON 非常简单。 我想要一些通用的东西,它不依赖于反射进行抽象,并且让我可以完全控制要呈现哪些属性,而无需用属性或其他声明来污染我的领域模型,因为这些东西完全与 UI 相关。
结果呢? 一个具有 Serialize()
方法的 "JSONObject
",它发出 JSON 代码。 这是该类
namespace MyJSON
{
/// <summary>
/// Delegate to determine how a value is pulled from the object
/// </summary>
/// <param name="instance">The instance to pull the property from</param>
/// <param name="property">The value of the instance</param>
/// <returns>The string representation of the value for that property</returns>
public delegate string PropertyValue<t>(T instance, string property);
/// <summary>
/// Class to help serialize AirWatch objects to the client
/// </summary>
public class JSONObject<T>
{
/// <summary>
/// The object to serialize
/// </summary>
private readonly T _object;
/// <summary>
/// A list of properties to serialize
/// </summary>
private readonly List<string> _properties;
/// <summary>
/// Reference to delegate to parse the value
/// </summary>
private readonly PropertyValue<t> _propValue;
/// <summary>
/// Constructor for JSON object
/// </summary>
/// <param name="instance">The entity instance</param>
/// <param name="properties">The list of properties to serialize</param>
/// <param name="propValue">The method to extract the property value</param>
public JSONObject(T instance, IEnumerable<string> properties,
PropertyValue<T> propValue)
{
_object = instance;
_properties = new List<string>(properties);
_propValue = propValue;
}
/// <summary>
/// Serialize to the JSON representation
/// </summary>
/// <returns>The JSON representation</returns>
public string Serialize()
{
StringBuilder json = new StringBuilder();
json.Append("{");
bool first = true;
foreach(string prop in _properties)
{
if (first)
{
first = false;
}
else
{
json.Append(",");
}
string value = _propValue(_object, prop);
json.Append(string.Format("\"{0}\":{1}", prop, EncodeJsString(value)));
}
json.Append("}");
return json.ToString();
}
}
}
JSON 对象接受 T
类型,可以是任何类型。 构造函数接收 "T
",以及一个数组和一个委托。 该数组是一个 string
列表,描述了我感兴趣的属性。 例如,我可能只想发送 id 和姓氏,因为我不在客户端脚本中使用其他属性。 最后,是 delegate
。 签名很简单:给定属性和实体,string
的值是什么? 这允许我注入逻辑以将 UI 属性映射到域属性。 发送数据的最简单方法是将它实现为一个 string
,然后在客户端上适当地操作它。 毕竟,JavaScript 本身并不知道我们的任何复杂对象。
最简单的用法就是简单地发送我的一个 Person
对象并显示该名称。 例如
<b>ID: </b> <span id="personId"> </span>
<b>Name: </b> <span id="personName"> </span>
在我自己的脚本中,我只需创建我的 JSON 对象并将其序列化输出
JSONObject<Person> jsonPerson = new JSONObject<Person>(
new Person { ID = 1, LastName="Likness" },
new[] { "id", "name" },
(entity,property) => property.Equals("id") ? entity.ID : entity.LastName
);
Page.ClientScript.RegisterClientScriptBlock(GetType(),GetType(),
string.Format("var person={0}",jsonPerson.Serialize()),true);
最后,我需要一些东西来为我连接它,我将选择 JQuery ...
<script type="text/javascript">
$(document).ready(function(){
$("#personId").html(person.id);
$("#personName").html(person.name);
});
</script>
script
块接受一个 type
(我只是使用我所在的页面或控件的 type
)、一个 key(每个 script 块应该是唯一的... 我再次在此处使用 type,但可以将其强类型化或设置为 const
等)、要发出的 JavaScript(来自 JSON 对象上的 serialize
方法),然后 true
告诉它包装我的 script
标签,因为我自己没有这样做。
这些对象可以作为回调的结果返回(只需将它们分配给 window.var
对象,以便它们可以全局访问并使用 eval
)用于动态绑定,或者您可能只需渲染一个对象数组,然后执行类似的操作
for (var x = 0; x < window.json_options.length; x++) {
var option = window.json_options[x];
$("#selBox").append("<option value=\"" +
option.id + "\"" + +(first ? " checked=\"checked\"" : "")
+ ">" + option.value + "</option>");
}
这将绑定下拉列表。 如果你正在与“hack”的冲动作斗争,因为我们正在连接 HTML ... 请记住,这正是 ASP.NET 在幕后为你所做的事情。 最后,控件是复杂的文本渲染引擎,它们发出浏览器可以管理的片段。
当然,下一步是创建一个 JSONList<T>
,我故意省略了编码脚本。 你可以在 Google 上搜索一些解决方案。