在做淘宝API的学习过程中,发现一个API的封装类库Top4NET对操作封装的比较好,试用了一下,效果非常不错,另外由于淘宝的API对象参数很多,多数是英文的,另一方面Top4NET的实体类对象备注信息很详细,因此可以考虑吧实体类的属性描述信息作为列表的表头说明使用。
我们看到他的Domain里面的实体类信息描述很详细,代码如下所示:
/// 商品结构
/// </summary>
[Serializable]
[JsonObject]
[XmlRoot( " item " )]
public class Item : BaseObject
{
/// <summary>
/// 商品编号
/// </summary>
[JsonProperty( " iid " )]
[XmlElement( " iid " )]
public string Iid { get ; set ; }
/// <summary>
/// 商品地址
/// </summary>
[JsonProperty( " detail_url " )]
[XmlElement( " detail_url " )]
public string DetailUrl { get ; set ; }
/// <summary>
/// 商品数字编号
/// </summary>
[JsonProperty( " num_iid " )]
[XmlElement( " num_iid " )]
public string NumIid { get ; set ; }
/// <summary>
/// 商品标题
/// </summary>
[JsonProperty( " title " )]
[XmlElement( " title " )]
public string Title { get ; set ; }
/// <summary>
/// 卖家昵称
/// </summary>
[JsonProperty( " nick " )]
[XmlElement( " nick " )]
public string Nick { get ; set ; }
我们看看Top4NET类库生成的字段描述信息,它是一个叫做Top4Net.xml的文件(VS自动生成出来的),结构如下所示:
这些是很详细的类库备注信息,如果能在代码中读取对应的属性备注信息出来,那么各项内容的显示,就不需要太多的手工字段的转义工作了,虽然在性能上有点点损失,但是开发效率上会提高不少。
现在的问题就是该如何才能正确读取到相关的信息,这个操作可以通过XML文档的检索实现的,我在测试的时候,发现可以通过3种方式来读取到正确节点的信息的。其中上面的Member中的Name第一个字符有T、P、M等字样,其中的T是类,P是属性,M是方法的意思。
/// 根据类属性名称,获取对应的备注信息(如果键名不存在,返回空)
/// </summary>
/// <param name="classPropertyName"> 类全局名称(带命名空间) </param>
/// <returns></returns>
public static string GetPropertySummary( string classPropertyName)
{
string filePath = Path.Combine(Application.StartupPath, " Top4Net.xml " );
string keyName = string .Format( " //doc/members/member[@name='P:{0}']/summary " , classPropertyName);
XPathDocument doc = new XPathDocument(filePath);
XPathNavigator nav = doc.CreateNavigator();
XPathNodeIterator iterator = nav.Select(keyName);
string result = "" ;
try
{
if (iterator.MoveNext())
{
XPathNavigator nav2 = iterator.Current.Clone();
result += nav2.Value;
}
}
catch (Exception ex)
{
;
}
return result.Trim();
}
/// <summary>
/// 根据类属性名称,获取对应的备注信息(如果键名不存在,返回空)
/// </summary>
/// <param name="classPropertyName"> 类全局名称(带命名空间) </param>
/// <returns></returns>
public static string GetPropertySummary2( string classPropertyName)
{
string filePath = Path.Combine(Application.StartupPath, " Top4Net.xml " );
string keyName = string .Format( " //doc/members/member[@name='P:{0}']/summary " , classPropertyName);
XmlDocument document = new XmlDocument();
document.Load(filePath);
string result = "" ;
XmlNode node = document.SelectSingleNode(keyName);
if (node != null )
{
result = node.FirstChild.Value;
}
return result.Trim();
}
/// <summary>
/// 根据类属性名称,获取对应的备注信息(如果键名不存在,返回空)
/// </summary>
/// <param name="classPropertyName"> 类全局名称(带命名空间) </param>
/// <returns></returns>
public static string GetPropertySummary3( string classPropertyName)
{
string strReturn = string .Empty;
try
{
string keyName = string .Format( " P:{0} " , classPropertyName);
string filePath = Path.Combine(Application.StartupPath, " Top4Net.xml " );
XmlDocument document = new XmlDocument();
document.Load(filePath);
XmlNodeList nodes = document.GetElementsByTagName( " member " );
for ( int i = 0 ; i < nodes.Count; i ++ )
{
// 获得将当前元素的key属性
XmlAttribute attribute = nodes[i].Attributes[ " name " ];
// 根据元素的第一个属性来判断当前的元素是不是目标元素
if (attribute != null && (attribute.Value == keyName))
{
XmlNode node = nodes[i].ChildNodes[ 0 ];
if (node != null )
{
strReturn = node.FirstChild.Value;
break ;
}
}
}
}
catch
{
;
}
return strReturn.Trim();
}
由于上述的方法参数classPropertyName是类的全称名字,因此我们需要通过反射方式获取对应的属性名称信息,由于属性名称的简称对我们也有用,因此编写一个API函数,返回Dictionary<string,string>类型即可。
/// 获取类属性的名称和全称字典列表
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static Dictionary < string , string > GetPropertyFullNameDict( object obj)
{
Dictionary < string , string > dict = new Dictionary < string , string > ();
Type t = obj.GetType();
PropertyInfo[] pi = t.GetProperties();
foreach (PropertyInfo info in pi)
{
if ( ! dict.ContainsKey(info.Name))
{
dict.Add(info.Name, string .Format( " {0}.{1} " , t.FullName, info.Name));
}
}
return dict;
}
最后我们在进一步封装,把实体类对象的备注信息取出来放到字典对象中,如下所示:
/// 获取类属性名称和描述信息的对照字典
/// </summary>
/// <param name="obj"> 实体类对象 </param>
/// <returns></returns>
public static Dictionary < string , string > GetPropertyAliasDict( object obj)
{
Dictionary < string , string > dict = new Dictionary < string , string > ();
Dictionary < string , string > propertyNameDict = XmlHelper.GetPropertyFullNameDict(obj);
StringBuilder sb = new StringBuilder();
foreach ( string simpleName in propertyNameDict.Keys)
{
string summary = XmlHelper.GetPropertySummary(propertyNameDict[simpleName]);
if ( string .IsNullOrEmpty(summary))
{
summary = simpleName; // 如果找不到对象的名称,那么取其属性名称作为Summary信息
}
if ( ! dict.ContainsKey(simpleName))
{
dict.Add(simpleName, summary);
}
}
return dict;
}
有了这个API函数,我们就可以随意的在界面中,通过极少的代码,实现表头中文化的自动转义了。下面我给我参考代码:
ItemsGetRequest itemReq = new ItemsGetRequest();
itemReq.Fields = " iid,title,nick,pic_url,cid,price,type,delist_time,post_fee,score,volume,location.city,location.state " ;
itemReq.Query = " 笔记本 " ;
// itemReq.Cid = "14";
itemReq.OrderBy = " volume:desc " ;
itemReq.PageNo = 1 ;
itemReq.PageSize = 40 ;
#region 给显示控件添加别名解析
// 特殊字段采用手工修改
this .winGridView1.AddColumnAlias( " Created " , " 创建时间 " );
this .winGridView1.AddColumnAlias( " Modified " , " 修改时间 " );
// 其他字段代码自动转义
Dictionary < string , string > dictAlias = XmlHelper.GetPropertyAliasDict( new Item());
foreach ( string simpleName in dictAlias.Keys)
{
this .winGridView1.AddColumnAlias(simpleName, dictAlias[simpleName]);
}
#endregion
// 显示列表信息
ResponseList < Item > itemRsp = client.Execute(itemReq, new ItemListJsonParser());
this .winGridView1.DataSource = itemRsp.Content;
this .winGridView1.PrintTitle = " 查询商品信息(不含类别) " ;
最后给出一个测试程序的界面截图,供参考:
取实体类备注信息作为界面展示用途,还可以应用在很多其他地方,淘宝Top4NET只是一个恰当的应用场景而已,对于大量备注完整的实体类,使用这些资源应该还是比较不错的选择。