AutoCAD 命令统计魔幻球的实现过程--(4)
这是这个系列的最后一篇,制作一个AutoCAD插件来获取AutoCAD的命令使用情况,并上传到云端服务。首先我使用AutoCAD.net plugin wizard创建一个AutoCAD 插件,这个向导会帮助我添加一些AutoCAD相关的引用。另外因为我要用到前面自定义的数据模型,在之前为了在这个项目中重用,我已经把他独立成一个单独的项目,现在在这个AutoCAD插件项目中添加到这个数据模型项目的引用。
本文连接:http://www.cnblogs.com/junqilian/archive/2013/03/25/2980097.html
在AutoCAD中获取命令的使用情况可以使用AutoCAD的一个非常简单的API,即监听Document 的CommandEnded事件。看下面的代码,首先定义了一个字典用于存储命令使用统计信息,然后定义了一个AutoCAD自定义命令,在这个命令中捕捉Document的Ended事件。在Document——Ended事件中,可以通过e.GobalCommandName取到执行成功的AutoCAD命令名字,添加到字典中。
private Dictionary<string, int> _commandHitDic = new Dictionary<string, int>();
[CommandMethod("ACV_MonitorCommandEvents")]
public void MonitorCommandEvents_Method()
{
SubscribeToDoc(Application.DocumentManager.MdiActiveDocument);
GetEditor().WriteMessage("Magic ball is listening, keep working... ");
}
public void SubscribeToDoc(Document doc)
{
doc.CommandEnded += new CommandEventHandler(doc_CommandEnded);
}
void doc_CommandEnded(object sender, CommandEventArgs e)
{
string commandName = e.GlobalCommandName;
// filter out the custom commands of this application
if (commandName.StartsWith("ACV"))
{
return;
}
AddCommandHit(commandName);
}
private void AddCommandHit(string commandName)
{
if (_commandHitDic.Keys.Contains<string>(commandName))
{
_commandHitDic[commandName]++;
}
else
{
_commandHitDic.Add(commandName, 1);
}
}
下面就是把字典中的统计信息上传到云端。前面的文章中已经结束了云端REST服务的实现,AutoCAD插件作为客户端只要发送REST请求即可。这里我使用了一个比较流行的类库RestSharp,废话不多说了,看代码:
[CommandMethod("ACV_UpdateToCloud")]
public void UpdateToCloud()
{
UserCommandsHit usrCmdsHit = null;
RestClient client = new RestClient(BASE_URL);
client.AddHandler("application/json", new JsonDeserializer());
usrCmdsHit = GetUserCommadsHitByUserName(_userName, client);
//CommandHit record with this username is not found in cloud
//Add one record for this user.
if (usrCmdsHit == null)
{
//add user command hit record
usrCmdsHit = BuildNewUserCommandsHitFromDictionary(_userName,_commandHitDic);
//POST to add new
AddNewToCloud(usrCmdsHit, client);
}
else
{
//update the user command hit with dictionary
usrCmdsHit = UpdateUserCommandsHitFromDictionary(usrCmdsHit,_commandHitDic);
//PUT to update
UpdateToCloud(usrCmdsHit, client);
}
GetEditor().WriteMessage("\n Your command usage statastic has been updated to cloud succesfully.");
GetEditor().WriteMessage("\n Keep working or open http://acadcommandwebviewer.cloudapp.net/ with a modern broswerto view the magic ball ;) ");
GetEditor().WriteMessage("\n Chrome/Firefox are recommended. ");
System.Diagnostics.Process.Start("http://acadcommandwebviewer.cloudapp.net/");
} private UserCommandsHit GetUserCommadsHitByUserName(
string userName,
RestClient client)
{
UserCommandsHit usrCmdsHit = null;
RestRequest reqGet = new RestRequest();
reqGet.Resource = "api/AcadCommands";
reqGet.Method = Method.GET;
reqGet.RequestFormat = DataFormat.Json;
reqGet.AddHeader("Accept", "Application/json");
reqGet.JsonSerializer = new RestSharp.Serializers.JsonSerializer();
reqGet.AddParameter("username", userName);
var respGet = client.Execute<UserCommandsHit>(reqGet);
if (respGet.StatusCode == System.Net.HttpStatusCode.OK)
{
if (respGet.Data != null)
{
usrCmdsHit = respGet.Data;
}
else
{
usrCmdsHit = Newtonsoft.Json.JsonConvert
.DeserializeObject<UserCommandsHit>(respGet.Content);
}
}
return usrCmdsHit;
}
private UserCommandsHit BuildNewUserCommandsHitFromDictionary(
string userName,
Dictionary<string, int> commandHitDic)
{
UserCommandsHit usrCmdsHit = new UserCommandsHit();
usrCmdsHit.UserName = userName;
List<CommandHit> list = new List<CommandHit>();
foreach (var cmdName in commandHitDic.Keys)
{
CommandHit ch = new CommandHit
{
CommandName = cmdName,
HitNumber = commandHitDic[cmdName]
};
list.Add(ch);
}
usrCmdsHit.CommandHits = list;
return usrCmdsHit;
} private UserCommandsHit UpdateUserCommandsHitFromDictionary(
UserCommandsHit usrCmdsHit,
Dictionary<string,int> commandHitDic)
{
foreach (var cmdName in commandHitDic.Keys)
{
int count = usrCmdsHit.CommandHits
.Where<CommandHit>(p => p.CommandName == cmdName)
.Count<CommandHit>();
if (count == 0)
{
CommandHit ch = new CommandHit
{
CommandName = cmdName,
HitNumber = commandHitDic[cmdName]
};
usrCmdsHit.CommandHits.Add(ch);
}
else
{
CommandHit ch = usrCmdsHit.CommandHits
.First<CommandHit>(p => p.CommandName == cmdName);
ch.HitNumber += commandHitDic[cmdName];
}
}
return usrCmdsHit;
}
private void AddNewToCloud(UserCommandsHit usrCmdsHit, RestClient client)
{
RestRequest reqPost = new RestRequest();
reqPost.Resource = "api/AcadCommands";
reqPost.Method = Method.POST;
reqPost.RequestFormat = DataFormat.Json;
reqPost.AddHeader("Content-Type", "application/json");
reqPost.JsonSerializer = new RestSharp.Serializers.JsonSerializer();
reqPost.AddBody(usrCmdsHit);
var respPost = client.Execute<UserCommandsHit>(reqPost);
if (respPost.StatusCode == System.Net.HttpStatusCode.Created)
{
_commandHitDic.Clear();
GetEditor().WriteMessage("\nUpdate to cloud successfully.");
}
else
{
GetEditor().WriteMessage("\n Error:" + respPost.StatusCode);
GetEditor().WriteMessage("\n" + respPost.Content);
}
}
private void UpdateToCloud(UserCommandsHit usrCmdsHit, RestClient client)
{
RestRequest reqPut = new RestRequest();
reqPut.Resource = "api/AcadCommands/" + usrCmdsHit.Id ;
reqPut.Method = Method.PUT;
reqPut.RequestFormat = DataFormat.Json;
reqPut.AddHeader("Content-Type", "application/json");
reqPut.JsonSerializer = new JsonSerializer();
reqPut.AddBody(usrCmdsHit);
var respPut = client.Execute<UserCommandsHit>(reqPut);
if (respPut.StatusCode == System.Net.HttpStatusCode.OK)
{
_commandHitDic.Clear();
GetEditor().WriteMessage("\nUpdate to cloud successfully.");
}
else
{
GetEditor().WriteMessage("\n Error:" + respPut.StatusCode);
GetEditor().WriteMessage("\n" + respPut.Content);
}
}
好了,整个过程也不复杂,总的来说就是通过REST和云端通信,把AutoCAD本地的信息上传到云端,进而可以在其他终端(浏览器,甚至手机)来做处理。这只是个小例子,也许你会有更实用的想法,不妨动手试试吧。