经过前两篇文章,我们已经可以得到了我们的花园的基本信息了,并用xml反序列化来映射到相应的实体类中,有了花园信息,我就就要来研究其一些动作的实现了,比如说:浇水、除草、收获、偷盗等等功能具体是怎么来实现的, 首先还是打开fiddler2抓一下包看看
收获:
GET /!house/!garden/havest.php?
verify=22842320%5F1062%5F22842320%5F1245934796%5Fb2a24c5dfb54cbeb1498d95d42b820a4&seedid=0&farmnum=13&fuid=0&r=0%2E24021180626004934 HTTP/1.1
成功
<data><leftnum>2</leftnum><stealnum>0</stealnum>
<num>2</num><seedname>雪莲</seedname>
<fruitpic>http://img.kaixin001.com.cn//i2/house/garden/crop/xuelian.swf
</fruitpic><ret>succ</ret></data>
失败
<data><ret>fail</ret><reason>这块地没有东西可收获</reason></data>
偷盗:
GET /!house/!garden/havest.php?
verify=22842320%5F1062%5F22842320%5F1245934796%5Fb2a24c5dfb54cbeb1498d95d42b820a4
&seedid=0
&farmnum=14
&fuid=7033784
&r=0%2E7748989406973124 HTTP/1.1
成功
<data><anti>0</anti><leftnum>46</leftnum><stealnum>1</stealnum>
<num>1</num><seedname>牧草</seedname>
<fruitpic>http://img.kaixin001.com.cn//i2/house/garden/crop3/gouweiba.swf
</fruitpic><ret>succ</ret></data>
失败
<data><anti>0</anti><ret>fail</ret><reason>已偷过,做人要厚道</reason></data>
犁地:
GET /!house/!garden/plough.php?
verify=22842320%5F1062%5F22842320%5F1245934796%5Fb2a24c5dfb54cbeb1498d95d42b820a4
&seedid=0
&farmnum=13
&fuid=0
&r=0%2E09461198281496763 HTTP/1.1
成功
<data><ret>succ</ret></data>
失败
<data><ret>fail</ret><reason>已经犁过了,该播种了</reason></data>
播种:
GET /!house/!garden/farmseed.php?
verify=22842320%5F1062%5F22842320%5F1245934796%5Fb2a24c5dfb54cbeb1498d95d42b820a4
&seedid=63
&farmnum=13
&fuid=0
&r=0%2E42840757546946406 HTTP/1.1
成功
<data><ret>succ</ret></data>
失败
<data><ret>fail</ret><reason>这里不可以种喔</reason></data>
上面是几种基本状态请求的URL和返回操作成功还是失败的XML,我们可以按照上一扁的方法把返回的XML进行反序列化来让我们的程序得到这些状态。
我们先分析每个请求都向服务器发送了什么信息,其中的参数大部发好理解,我们就不说了,就一个verify和一个r不太清楚做什么用,我尝试着在浏览器里把这两个参数去掉然后访问,结果是,r有没有都无所谓,哪我们就不考虑它了,还有一个缺不可缺少,而且每次登录这个verify都会变化,我们哪里去取到这个值呢, 在分析了多个页面的原代码后,我们在http://www.kaixin001.com/!house/index.php页面的代码中找到了这串值,
先也别管他起什么作用了,把它抓出来才是正经。怎么抓出来,这个返回的可不是XML是一个乱七八糟的HTML,而且这串值还在一段js代码中,好在我们还有正则表达式这个武器,一切都迎刃而解了,在VS中敲出如下代码:
由于这个值在每一次登录以后不会改变,所以我的做好是在登录后就调用这个函数,并保存在一个类的公有变量中。
获得了这个verify的值后,我们就可以放心的写接下来的代码了,接下了就简单了,按上一篇的方法,写就可以了,先设计实体代码
[XmlRoot(ElementName = "data")]
public class ReturnInfo
{
public string ret;
public string reason;
public int anti;
}
大部分时候返回的XML就包含这些值,只有收获成功的时候才返回更多的信息,我们可以把这种情况做为Returninfo的一个子类来实现
Code
[XmlRoot(ElementName = "data")]
public class havestInfo:ReturnInfo
{
public int leftnum { get; set; }
public int stealnum { get; set; }
public int num { get; set; }
public string seedname { get; set; }
}
我们的操作代码也很简单
Code
/// <summary>
/// 收获
/// </summary>
/// <param name="fuid"></param>
/// <param name="seedid"></param>
/// <param name="farmnum"></param>
/// <returns></returns>
public ReturnInfo HavestFarm(int fuid, int seedid, int farmnum)
{
string url = string.Format(havesturl,
this.g_verify,
seedid.ToString(),
farmnum.ToString(),
fuid.ToString());
string str = this.myrequest.RequestByGet(url);
byte[] bytes = Encoding.GetEncoding("UTF-8").GetBytes(str);
Stream s = new MemoryStream();
s.Write(bytes, 0, bytes.Length);
s.Position = 0;
XmlSerializer xmls = new XmlSerializer(typeof(ReturnInfo));
ReturnInfo ret = (ReturnInfo)xmls.Deserialize(s);
return ret;
}
这个函数基本上符合了我们的要求,但是和我们昨天的代码对比一下,我们发现除了返回的类型不同,其它大部分的代码都重复了
这些重复的代码,我们每一个操作都要写,太麻烦了,万一要修改哪不完玩了,重构一下,一开始我的办法是把这几行代码写到一个单独的函数中,但是我们很快发现,下面两句代码也只是稍有不同
就这一点点的差别用普通函数来重构就麻烦了,但是好在C#2.0以后有了泛型这个好东东,看我七十二变
Code
public T Deserialize<T>(string url)
{
return Deserialize<T>(url, "");
}
public T Deserialize<T>(string url,string postdata)
{
//Stream s=StrtoStream(url);
string str="";
if (postdata == "")
{
str = this.myrequest.RequestByGet(url);
}
else
{
str = this.myrequest.RequestByPost(url, postdata);
}
try
{
byte[] bytes = Encoding.GetEncoding("UTF-8").GetBytes(str);
Stream s = new MemoryStream();
s.Write(bytes, 0, bytes.Length);
s.Position = 0;
XmlSerializer xmls = new XmlSerializer(typeof(T));
T ret = (T)xmls.Deserialize(s);
return ret;
}
catch (Exception ex)
{
Log.LogOut(ex.Message);
return default(T);
}
}
接下来我们的代码就变成了这样了
Code
public GardenInfo GetGardenInfo(int uid)
{
string url = string.Format("http://www.kaixin001.com/!house/!garden//getconf.php?verify={0}&fuid={1}",this.g_verify,uid);
GardenInfo curGardenInfo = this.Deserialize<GardenInfo>(url);
return curGardenInfo;
}
/// <summary>
/// 收获
/// </summary>
/// <param name="fuid"></param>
/// <param name="seedid"></param>
/// <param name="farmnum"></param>
/// <returns></returns>
public ReturnInfo HavestFarm(int fuid, int seedid, int farmnum)
{
string url = string.Format(havesturl,
this.g_verify,
seedid.ToString(),
farmnum.ToString(),
fuid.ToString());
return (ReturnInfo)this.Deserialize<havestInfo>(url);
}
/// <summary>
/// 浇水
/// </summary>
/// <param name="fuid"></param>
/// <param name="seedid"></param>
/// <param name="farmnum"></param>
/// <returns></returns>
public ReturnInfo WaterFarm(int fuid, int seedid, int farmnum)
{
string url = string.Format(waterurl,
this.g_verify,
seedid.ToString(),
fuid.ToString(),
farmnum.ToString());
return this.Deserialize<ReturnInfo>(url);
}
/// <summary>
/// 买种子
/// </summary>
/// <param name="num">要卖的种子数量</param>
/// <param name="seedid">要卖的种子类型</param>
/// <returns></returns>
public ReturnInfo BuySeed(int num, int seedid)
{
string PostData = string.Format(buySeedPost,
this.g_verify,
num.ToString(),
seedid.ToString());
return Deserialize<ReturnInfo>(buySeedUrl, PostData);
}
/// <summary>
/// 除草
/// </summary>
/// <param name="fuid"></param>
/// <param name="seedid"></param>
/// <param name="farmnum"></param>
/// <returns></returns>
public ReturnInfo KillGrass(int fuid, int seedid,int farmnum)
{
string PostData = string.Format(KillGrassPost,
this.g_verify,
seedid.ToString(),
fuid.ToString(),
farmnum.ToString());
return Deserialize<ReturnInfo>(KillGrassUrl, PostData);
}
是不是清爽了好多!