利用缓存、Timer间隔时间发送微信的实例,很有用的例子
//Class WechatOfferExcutor
此类为微信触发类,属于上层调用类,其中有用到用静态变量缓存offer信息,Task异步执行发送方法等
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Velites.Utility.SharedLibrary;
using Newtonsoft.Json;
using System.Configuration;
namespace xxx.Peripheral.Wechat
{
[ParametrType(typeof(WechatOfferParameter))]
public class WechatOfferExcutor : MemberOfferExecutorBase<WechatOfferParameter>
{
static KeyValuePair<long, WechatOfferParameter> offerInfo = new KeyValuePair<long, WechatOfferParameter>();
static WechatBatchProcess proc = new WechatBatchProcess(Send);
protected override IOfferExecutionResult ExecuteWithIDataAndMember(IData data, IMember member, WechatOfferParameter offer)
{
bool isValid = AssertHits(data, member, offer);
LogStub.Log(new LogEntry("txt - AssertHits isValid", LogStub.LOG_LEVEL_ERROR));
if (isValid && !string.IsNullOrWhiteSpace(offer.Content))
{
string memCode = member.GetProperty(ThreeMMemberEntitySchema.ThreeMMember.CODE).ToString();
string toWechat = member.GetProperty(ThreeMMemberEntitySchema.ThreeMMember.WECHAT_OPENID).ToString();
List<ImgItem> itemList = new List<ImgItem>()
{
new ImgItem() {
title = offer.Subject,
content = offer.Content
}
};
LogEntry entry = new LogEntry(string.Format("txt - 微信发送开始, memCode = {0}, wechatOpenID = {1}, offerID = {2}", memCode, toWechat, offer.OfferID), LogStub.LOG_LEVEL_ERROR);
LogStub.Log(entry);
proc.AddOpenIDAndSendWechat(offer.OfferID, toWechat, itemList, offer.ExecuteTime);
//EmailServiceApiConfigurationHub.Instance.EmailProvider.Provide().Send(wechat);
LogEntry endEntry = new LogEntry("txt - 微信发送结束", LogStub.LOG_LEVEL_ERROR);
LogStub.Log(endEntry);
}
return null;
}
private static void Send(List<string> openIDs, List<ImgItem> imgDesc)
{
//注意,此处必须为异步调用发送方法,否则可能导致发送超时,以至于发送失败
Task.Run(() => WechatUtility.SendText(openIDs, imgDesc));
offerInfo = new KeyValuePair<long, WechatOfferParameter>();
}
public bool AssertHits(IData data, IMember member, WechatOfferParameter offer)
{
bool ret = true;
if (data == null || member == null || offer == null || member.GetProperty(ThreeMMemberEntitySchema.ThreeMMember.WECHAT_OPENID) == null
|| string.IsNullOrWhiteSpace(member.GetProperty(ThreeMMemberEntitySchema.ThreeMMember.WECHAT_OPENID).ToString()))
{
ret = false;
return ret;
}
return ret;
}
public override WechatOfferParameter ParseToParameter(JObject jOffer, IOffer offer)
{
if (offerInfo.Key != offer.ID)
{
WechatOfferParameter wechatOffer = base.ParseToParameter(jOffer, offer);
wechatOffer.Category = offer.CategoryKey;
var offerParameterToken = JToken.Parse(offer.Parameter);
if (offerParameterToken["content"] != null)
{
wechatOffer.Content = offerParameterToken["content"].ToString();
wechatOffer.Subject = offer.Name;
wechatOffer.OfferID = offer.ID;
//此处给发送时间赋值
//如果是市场活动,没有执行时间,那么可以设置为当前时间的5分钟之后
//测试时可以设置为10秒
//wechatOffer.ExecuteTime = DateTime.Now.AddSeconds(10);
wechatOffer.ExecuteTime = DateTime.Now.AddMinutes(5);
var interval = ConfigurationManager.AppSettings["ActivityInterval"];
if (interval != null)
{
wechatOffer.ExecuteTime = DateTime.Now.AddMinutes(Int32.Parse(interval.ToString()));
}
if (jOffer != null)
{
IDictionary<string, JToken> data = JsonConvert.DeserializeObject<JObject>(jOffer.ToString());
var item = data.Where(p => p.Key.ToLower() == "executetime");
if (item != null && item.Any())
{
wechatOffer.ExecuteTime = Convert.ToDateTime(item.FirstOrDefault().Value);
}
}
offerInfo = new KeyValuePair<long, WechatOfferParameter>(offer.ID, wechatOffer);
return wechatOffer;
}
}
return offerInfo.Value;
}
}
}
//Class WechatBatchProcess
此类是发送微信的中间处理类,包括了Timer间隔触发等,并发处理Lock机制等,其他的项目可以借鉴此类。
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
namespace ThreeM.Peripheral.Wechat
{
public class WechatBatchProcess
{
List<SendInfo> SendInfoList = new List<SendInfo>();
Action<List<string>, List<ImgItem>> sendAct { set; get; }
Timer timer;
public WechatBatchProcess(Action<List<string>, List<ImgItem>> act)
{
timer = new Timer();
sendAct = act;
//正式的可以改10分钟,测试时可以为30000即30秒
timer.Interval = 600000;
var interval = ConfigurationManager.AppSettings["TimerInterval"];
if (interval != null)
{
timer.Interval = Int32.Parse(interval);
}
timer.AutoReset = false;
timer.Elapsed += new System.Timers.ElapsedEventHandler(Timers_Timer_Elapsed);
}
void Timers_Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
lock (this)
{
var itemList = SendInfoList.Where(p => p.SendTime <= DateTime.Now).ToList();
SendInfoList = SendInfoList.Where(p => p.SendTime > DateTime.Now).ToList();
foreach (var item in itemList)
{
Send(item);
}
if (SendInfoList.Any())
{
timer.Start();
}
}
}
public void AddOpenIDAndSendWechat(long OfferID, string OpenID, List<ImgItem> ImgDesc, DateTime? SendTime)
{
if (!string.IsNullOrWhiteSpace(OpenID) && ImgDesc != null && ImgDesc.Any())
{
lock (this)
{
var item = SendInfoList.FirstOrDefault(p => p.OfferID == OfferID);
if (item == null)
{
item = new SendInfo()
{
OfferID = OfferID,
OpenidList = new List<string>(),
ImgDesc = ImgDesc,
};
SendInfoList.Add(item);
}
item.SendTime = SendTime;
item.OpenidList.Add(OpenID);
}
timer.Start();
}
}
private void Send(SendInfo item)
{
if (item.OpenidList.Any())
{
sendAct(item.OpenidList, item.ImgDesc);
}
}
}
public class SendInfo
{
public List<string> OpenidList { get; set; }
public List<ImgItem> ImgDesc { get; set; }
public long OfferID { get; set; }
public DateTime? SendTime { get; set; }
}
}
//Class WechatUtility
此类为基础工具类,包含了发送微信时需要的HttpPost请求等方法,
包括文本请求和多张图片请求等,是一个非常有用的工具类
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Configuration;
using System.Collections.Specialized;
using Velites.Utility.SharedLibrary;
namespace xxx.Peripheral.Wechat
{
public class WechatUtility
{
public static string SendText(List<string> openIDList, string content)
{
string url = ConfigurationManager.AppSettings["wechatImgUrl"];
string result = string.Empty;
if (openIDList != null && openIDList.Any() && !string.IsNullOrWhiteSpace(content))
{
string param = string.Format("open_ids={0}&text={1}", string.Join(",",openIDList), content);
result = HttpPostData(url, param);
}
return result;
}
public static string SendText(List<string> openIDList, List<ImgItem> imgDesc)
{
string url = ConfigurationManager.AppSettings["wechatImgUrl"];
string result = string.Empty;
var imgInfo = imgDesc.FirstOrDefault();
if (openIDList != null && openIDList.Any() && !string.IsNullOrWhiteSpace(imgInfo.content))
{
//微信群发要求至少2个账号才能发送,如果只有一个时,添加一个相同的微信号
if (openIDList.Count() == 1)
{
openIDList.Add(openIDList.FirstOrDefault());
}
string param = string.Format("open_ids={0}&text={1}", string.Join(",", openIDList), imgInfo.content);
result = HttpPostData(url, param);
}
return result;
}
public static string SendImgAndText(List<string> openIDList, string title, string content, string filePath)
{
string url = ConfigurationManager.AppSettings["wechatImgUrl"];
string result = string.Empty;
if (openIDList != null && openIDList.Any() && !string.IsNullOrWhiteSpace(content))
{
NameValueCollection col = new NameValueCollection();
//col.Add("media", filePath);
col.Add("title", title);
col.Add("content", content);
col.Add("open_ids", string.Join(",", openIDList));
result = HttpPostData(url, 60000, "media1", filePath, col);
}
return result;
}
public static string SendImgAndText(List<string> openIDList, List<ImgItem> imgDesc)
{
string url = ConfigurationManager.AppSettings["wechatImgUrl"];
string result = string.Empty;
if (openIDList != null && openIDList.Any() && imgDesc != null)
{
Dictionary<string, string> imgDic = new Dictionary<string, string>();
foreach (var item in imgDesc)
{
imgDic.Add(item.name, item.path);
}
NameValueCollection col = new NameValueCollection();
col.Add("imgDesc", Newtonsoft.Json.JsonConvert.SerializeObject(imgDesc));
col.Add("open_ids", string.Join(",", openIDList));
result = HttpPostData(url, 60000, imgDic, col);
}
return result;
}
public static string HttpPostData(string url, string param)
{
LogEntry entry = new LogEntry("发送微信文本开始-HttpPostData -- " + param, LogStub.LOG_LEVEL_ERROR);
LogStub.Log(entry);
var result = string.Empty;
//注意提交的编码 这边是需要改变的 这边默认的是Default:系统当前编码
byte[] postData = Encoding.UTF8.GetBytes(param);
// 设置提交的相关参数
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
Encoding myEncoding = Encoding.UTF8;
request.Method = "POST";
request.KeepAlive = false;
request.AllowAutoRedirect = true;
request.ContentType = "application/x-www-form-urlencoded";
request.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)";
request.ContentLength = postData.Length;
// 提交请求数据
System.IO.Stream outputStream = request.GetRequestStream();
outputStream.Write(postData, 0, postData.Length);
outputStream.Close();
HttpWebResponse response;
Stream responseStream;
StreamReader reader;
string srcString;
response = request.GetResponse() as HttpWebResponse;
responseStream = response.GetResponseStream();
reader = new System.IO.StreamReader(responseStream, Encoding.GetEncoding("UTF-8"));
srcString = reader.ReadToEnd();
result = srcString; //返回值赋值
reader.Close();
entry = new LogEntry("发送微信文本结束-HttpPostData -- " + result, LogStub.LOG_LEVEL_ERROR);
LogStub.Log(entry);
return result;
}
private static string HttpPostData(string url, int timeOut, string fileKeyName,
string filePath, NameValueCollection stringDict)
{
string fileKeyName2 = "media2";
string filePath2 = @"C:\Users\gaoj007\Pictures\1aliuh.jpg";
string responseContent;
var memStream = new MemoryStream();
var webRequest = (HttpWebRequest)WebRequest.Create(url);
// 边界符
var boundary = "---------------" + DateTime.Now.Ticks.ToString("x");
// 边界符
var beginBoundary = Encoding.ASCII.GetBytes("--" + boundary + "\r\n");
var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
// 最后的结束符
var endBoundary = Encoding.ASCII.GetBytes("--" + boundary + "--\r\n");
// 设置属性
webRequest.Method = "POST";
webRequest.Timeout = timeOut;
webRequest.ContentType = "multipart/form-data; boundary=" + boundary;
// 写入文件
const string filePartHeader =
"Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n" +
"Content-Type: application/octet-stream\r\n\r\n";
var header = string.Format(filePartHeader, fileKeyName, filePath);
var headerbytes = Encoding.UTF8.GetBytes(header);
memStream.Write(beginBoundary, 0, beginBoundary.Length);
memStream.Write(headerbytes, 0, headerbytes.Length);
var buffer = new byte[1024];
int bytesRead; // =0
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
{
memStream.Write(buffer, 0, bytesRead);
}
//第二章图片
//memStream.Write(beginBoundary, 0, beginBoundary.Length);
//var aaa = Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
//memStream.Write(aaa, 0, aaa.Length);
string nxetFileFormat = "\r\n--" + boundary + "\r\n" + filePartHeader;
header = string.Format(nxetFileFormat, fileKeyName2, filePath2);
headerbytes = Encoding.UTF8.GetBytes(header);
memStream.Write(headerbytes, 0, headerbytes.Length);
fileStream = new FileStream(filePath2, FileMode.Open, FileAccess.Read);
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
{
memStream.Write(buffer, 0, bytesRead);
}
// 写入字符串的Key
var stringKeyHeader = "\r\n--" + boundary +
"\r\nContent-Disposition: form-data; name=\"{0}\"" +
"\r\n\r\n{1}\r\n";
foreach (byte[] formitembytes in from string key in stringDict.Keys
select string.Format(stringKeyHeader, key, stringDict[key])
into formitem
select Encoding.UTF8.GetBytes(formitem))
{
memStream.Write(formitembytes, 0, formitembytes.Length);
}
// 写入最后的结束边界符
memStream.Write(endBoundary, 0, endBoundary.Length);
webRequest.ContentLength = memStream.Length;
var requestStream = webRequest.GetRequestStream();
memStream.Position = 0;
var tempBuffer = new byte[memStream.Length];
memStream.Read(tempBuffer, 0, tempBuffer.Length);
memStream.Close();
requestStream.Write(tempBuffer, 0, tempBuffer.Length);
requestStream.Close();
var httpWebResponse = (HttpWebResponse)webRequest.GetResponse();
using (var httpStreamReader = new StreamReader(httpWebResponse.GetResponseStream(),
Encoding.GetEncoding("utf-8")))
{
responseContent = httpStreamReader.ReadToEnd();
}
fileStream.Close();
httpWebResponse.Close();
webRequest.Abort();
return responseContent;
}
private static string HttpPostData(string url, int timeOut, Dictionary<string, string> imgDic, NameValueCollection stringDict)
{
LogEntry entry = new LogEntry("发送微信图片开始-HttpPostData open_ids-- " + stringDict["open_ids"], LogStub.LOG_LEVEL_ERROR);
LogStub.Log(entry);
try
{
entry = new LogEntry("发送微信图片开始-HttpPostData imgDic-- " + string.Join(",", imgDic), LogStub.LOG_LEVEL_ERROR);
LogStub.Log(entry);
entry = new LogEntry("发送微信图片开始-HttpPostData imgDic-- first--" + imgDic.FirstOrDefault().Key + " -- " +
imgDic.FirstOrDefault().Value + "--last--" + imgDic.LastOrDefault().Key + " -- " + imgDic.LastOrDefault().Value + "--count--" + imgDic.Count(), LogStub.LOG_LEVEL_ERROR);
LogStub.Log(entry);
var firstImg = imgDic.FirstOrDefault();
string fileKeyName = firstImg.Key;
string filePath = firstImg.Value;
string responseContent;
var memStream = new MemoryStream();
var webRequest = (HttpWebRequest)WebRequest.Create(url);
// 边界符
var boundary = "---------------" + DateTime.Now.Ticks.ToString("x");
// 边界符
var beginBoundary = Encoding.ASCII.GetBytes("--" + boundary + "\r\n");
//var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
// 最后的结束符
var endBoundary = Encoding.ASCII.GetBytes("--" + boundary + "--\r\n");
// 设置属性
webRequest.Method = "POST";
webRequest.Timeout = timeOut;
webRequest.ContentType = "multipart/form-data; boundary=" + boundary;
// 写入文件
const string filePartHeader =
"Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n" +
"Content-Type: application/octet-stream\r\n\r\n";
var header = string.Format(filePartHeader, fileKeyName, filePath);
var headerbytes = Encoding.UTF8.GetBytes(header);
memStream.Write(beginBoundary, 0, beginBoundary.Length);
memStream.Write(headerbytes, 0, headerbytes.Length);
//var buffer = new byte[1024];
//int bytesRead; // =0
//while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
//{
// memStream.Write(buffer, 0, bytesRead);
//}
WebClient wc = new WebClient();
byte[] buffer = wc.DownloadData(filePath);
memStream.Write(buffer, 0, buffer.Length);
string imgName = string.Empty;
string imgPath = string.Empty;
foreach (var img in imgDic.Where(p => p.Key != fileKeyName))
{
imgName = img.Key;
imgPath = img.Value;
string nxetFileFormat = "\r\n--" + boundary + "\r\n" + filePartHeader;
header = string.Format(nxetFileFormat, imgName, imgPath);
headerbytes = Encoding.UTF8.GetBytes(header);
memStream.Write(headerbytes, 0, headerbytes.Length);
//fileStream = new FileStream(imgPath, FileMode.Open, FileAccess.Read);
//while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
//{
// memStream.Write(buffer, 0, bytesRead);
//}
buffer = wc.DownloadData(imgPath);
memStream.Write(buffer, 0, buffer.Length);
}
// 写入字符串的Key
var stringKeyHeader = "\r\n--" + boundary +
"\r\nContent-Disposition: form-data; name=\"{0}\"" +
"\r\n\r\n{1}\r\n";
foreach (byte[] formitembytes in from string key in stringDict.Keys
select string.Format(stringKeyHeader, key, stringDict[key])
into formitem
select Encoding.UTF8.GetBytes(formitem))
{
memStream.Write(formitembytes, 0, formitembytes.Length);
}
// 写入最后的结束边界符
memStream.Write(endBoundary, 0, endBoundary.Length);
webRequest.ContentLength = memStream.Length;
var requestStream = webRequest.GetRequestStream();
memStream.Position = 0;
var tempBuffer = new byte[memStream.Length];
memStream.Read(tempBuffer, 0, tempBuffer.Length);
memStream.Close();
requestStream.Write(tempBuffer, 0, tempBuffer.Length);
requestStream.Close();
var httpWebResponse = (HttpWebResponse)webRequest.GetResponse();
using (var httpStreamReader = new StreamReader(httpWebResponse.GetResponseStream(),
Encoding.GetEncoding("utf-8")))
{
responseContent = httpStreamReader.ReadToEnd();
}
//fileStream.Close();
httpWebResponse.Close();
webRequest.Abort();
entry = new LogEntry("发送微信图片结束-HttpPostData -- " + responseContent, LogStub.LOG_LEVEL_ERROR);
LogStub.Log(entry);
return responseContent;
}
catch (Exception er)
{
entry = new LogEntry("发送微信图文发生异常 -- HttpPostData -- " + er.ToString(), LogStub.LOG_LEVEL_ERROR);
LogStub.Log(entry);
}
return null;
}
}
}
利用缓存、Timer间隔时间发送微信的实例,很有用的例子的更多相关文章
- 小笔记:Timer定时间隔时间操作
小笔记:Timer定时间隔时间操作,后面有时间再补充和完善: public class TimingSvc { /// <summary> /// 定时器,执行定时任务 /// </ ...
- Python3.x:简单时间调度Timer(间隔时间执行)
Python3.x:简单时间调度Timer(间隔时间执行) threading模块中的Timer能够帮助实现定时任务,而且是非阻塞的: 代码: import threading import time ...
- python使用itchat发送微信消息提醒
最近在学习一点python,先找了找有趣的应用,实际修改跑了一下提高兴趣程度. 找到itchat,它的简介是这样的: “itchat是一个开源的微信个人号接口,使用python调用微信从未如此简单. ...
- 使AJAX调用尽可能利用缓存特性
优化网站设计(十四):使AJAX调用尽可能利用缓存特性 前言 网站设计的优化是一个很大的话题,有一些通用的原则,也有针对不同开发平台的一些建议.这方面的研究一直没有停止过,我在不同的场合也分享过这样的 ...
- Java:利用java Timer类实现定时执行任务的功能
一.概述 在java中实现定时执行任务的功能,主要用到两个类,Timer和TimerTask类.其中Timer是用来在一个后台线程按指定的计划来执行指定的任务.TimerTask一个抽象类,它的子类代 ...
- 利用fiddler和mock调试本地微信网页
利用fiddler和mock调试本地微信网页 微信公众号网页是比较特殊的页面,普通页面直接打开即可访问,但对于需要请求微信相关接口的部分需要安全域名认证.这导致了使用mock数据进行开发的页面没办法走 ...
- c/c++ linux epoll系列3 利用epoll_wait设置timeout时间长度
linux epoll系列3 利用epoll_wait设置timeout时间长度 epoll_wait函数的第四个参数可以设置,epoll_wait函数的等待时间(timeout时间长度). 例子1, ...
- Java定时任务:利用java Timer类实现定时执行任务的功能
一.概述 在java中实现定时执行任务的功能,主要用到两个类,Timer和TimerTask类.其中Timer是用来在一个后台线程按指定的计划来执行指定的任务. TimerTask一个抽象类,它的子类 ...
- [.net 面向对象程序设计进阶] (15) 缓存(Cache)(二) 利用缓存提升程序性能
[.net 面向对象程序设计进阶] (15) 缓存(Cache)(二) 利用缓存提升程序性能 本节导读: 上节说了缓存是以空间来换取时间的技术,介绍了客户端缓存和两种常用服务器缓布,本节主要介绍一种. ...
随机推荐
- U菜1G变化8M该解决方案
我有一个大小1G纽曼U菜,不幸中毒一年前,格式化后你刚刚离开8M该.然后不再格式正确. 尽管只有8M,但始终我觉得扔了可惜.曾经,它已被搁置.昨天突然心血来潮,我们决定尝试.活马医.想不到最后居然被我 ...
- hibernate的通配符比拼接sql到底好在哪?
Hibernate对于刚接触的人来说,通配符只是提供了另一种组合sql的方式.接触的久了,熟悉之后,才能够真正理解通配符在Hibernate中起到的作用 主要作用有两点: 1,避免sql注入 hibe ...
- Java线程学习笔记(两) 线程异常处理
线程捕获异常: 情况下,我们在main()方法里是捕捉不到线程的异常的,比例如以下面代码: public class ExceptionThread implements Runnable{ @Ove ...
- hdu 1150 Machine Schedule(最小顶点覆盖)
pid=1150">Machine Schedule Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/327 ...
- Myeclipse 10/2014 配置插件(svn、maven、properties、velocity)方法
一.构造SVN具体说明 什么是SVN? 管理软件开发过程中的版本控制工具. 以下会以两种方式来介绍怎么安装svn,myeclipse安装SVN插件步骤.以myeclipse 2014为例,第一种是最常 ...
- 【Android进阶】Activity和Fragement中onSaveInstanceState()的使用详解
在activity(或者是fragement)被杀掉之前调用保存每个实例的状态,以保证该状态可以在onCreate(Bundle)或者onRestoreInstanceState(Bundle) (传 ...
- W3C DOM 事件模型(简述)
1.事件模型 由于事件捕获与冒泡模型都有其长处和解释,DOM标准支持捕获型与冒泡型,能够说是它们两者的结合体.它能够在一个DOM元素上绑定多个事件处理器,而且在处理函数内部,thiskeyword仍然 ...
- iPhone&iPad DFU及恢复模式刷机、降级教程
再次提醒,刷机需慎重处理. http://blog.csdn.net/ztp800201/article/details/11980643 iphone一共同拥有三种工作模式,各自是正常模式,恢复模式 ...
- Design Pattern Command 命令设计模式
这种设计模式是使用不同类的包裹不同的命令,达到什么样的命令执行什么操作. 有可能进一步利用map您最喜欢的对接命令字. 正在运行的类实际上已经包含了操作的所有需求,例如: class SuperMak ...
- ASP.NET MVC4实现URL伪静态
1.在Web.config添加节点配置: <system.webServer> <modules runAllManagedModulesForAllRequests="t ...