[转载] Face.com 开放 API

mikel阅读(1222)

[转载]Dreamer’s Blog » Face.com 开放 API.

哈哈,发现一个很好玩的东西:Atuo Smiley 。它是一个运行在后台的程序,功能很简单,就是当它通过摄像头检测到你在笑的时候自动打出一个 🙂 出来。这个程序可以让你方便地在邮件中加入笑脸,还可以强制你在和别人聊天的时候保持诚实!不能明明很开心却强忍住笑耍别人,那样是不对的!

演示 Demo (是 vimeo 的视频,需翻墙)

另外,这个东西是开源的,有兴趣的可以去研究一下源码。

程序和源码下载请去原文查看

UPDATE:这个程序好像只支持 Mac OS, 之前没注意,不好意思。

[转载]asp.net页面出错时的处理方法

mikel阅读(950)

[转载]asp.net页面出错时的处理方法 – 总想拥有自己的天空 – 博客园.

1.第一种做法,在Web.config文件配置

<system.web>
<customErrors defaultRedirect=~/ErrorPage.aspx
mode
=RemoteOnly>
</customErrors>
</system.web>

defaultRedirect属性用来指明当aspx页面发生了未处理错误时导向的页面; 但ASP.NET使用重定向机制来重新导航错误页面,这样错误信息就会丢失,也就是说我们用 Server.GetLastError()获得的Exception对象始终是空的。虽然可以提示用户出错,并提供一个返回出错页面的链接,却不能给管 理员一个很好的错误提示。

2.第二种做法:在global文件里的 Application_Error方法中处理

代码

然后在ErrorPage.aspx页面显示一些好友的提示信息.

3.第三种做法:在Page_Error事件里面处理

代码

我经常的做法是使用第二种方法,然后再写一个发送短信的方法(调用移动的短信借口),这样的话程序出错的时候,管理员可以收到程序出错的信息。

[转载]C#调用新浪微博API生成RSS资源文件

mikel阅读(1160)

[转载]C#调用新浪微博API生成RSS资源文件 – 一点一滴的Beer – 博客园.

C#调用新浪微博API生成RSS资源文件

作者:一点一滴的Beer 个人主页:http://beer.cnblogs.com

新浪微博现在好像势头很猛,很多人在创立自己的微博客的时候,开始出于好奇,都会跟随很多人,久而久之,自己的好友人数超过100后,那么你就发 现,你已经完全淹没在信息的洪流中了,你跟随了那么多人,很多人都是今后可能永远都不会想起,也永远也不会看到的人,这显然与“关注”的目的是相背的,更 有时候可能你只是想看下你认识的人的消息更新了没有,但是显然你不可能每次都一个个到自己的关注人物表中点开然后再一一访问他的主页,这样操作太繁琐了。

用过RSS阅读器的用户可能都体会到RSS阅读器在获取信息的优越性了吧。它能实时跟踪RSS资源的更新,并显示更新数目到指定的订阅资源后面,可 以让用户有针对性地查看信息,让用户主动地去获取信息,而不再是被动地接受信息了,这对于解决微博的“信息洪流”问题是很有效的。

笔者花费了几天时间,终于写了一个程序,用于获取指定用户的好友,并存储备份到ACCESS数据库中,然后生成一个RSS阅读资源。不敢独享,所以 开源和大家分享。今后如果有时间,我想再将它做成一个桌面软件,方便一般不懂程序的用户来操作,这都是后话了吧。

1. 新浪微博RSS订阅第三方网站

新浪微博本身没有提供RSS订阅,但是到网上搜索,发现了一个第三方的网站,提供新浪微博的RSS资源,所以,本文的RSS订阅说白了都是基于这个 第三方网站的。

http://log.medcl.net/item/2010/02/sina-bo-rss-subscribe-feed-generate-micro/

2. 网上通用的OPML文件的XML格 式

下面是从Google Reader中导出的opml文件,这是网络RSS阅读器甚至所有RSS阅读器的标准格式吧,至少“鲜果”,“有道”这些比较流行的在线阅读器都支持这个 格式的文件导入。

<?xml version="1.0" encoding="UTF-8"?>
<opml version="1.0">
	<head>
		<title>subscriptions</title>
		<dateCreated>2010-05-16 15:45:03</dateCreated>
		<ownerName></ownerName>
	</head>
	<body>
		<outline text="微博客" title="微博客">			
			<outline text="冷笑话(1567852087)" 
				title="冷笑话(1567852087)" type="rss"
				htmlUrl="http://t.sina.com.cn/1567852087" 
				xmlUrl="http://medcl.net/SinaRss.aspx?uid=1567852087" />
			<outline text="后宫优雅(1665289110)" 
				title="后宫优雅(1665289110)" type="rss"
				htmlUrl="http://t.sina.com.cn/1665289110" 
				xmlUrl="http://medcl.net/SinaRss.aspx?uid=1665289110" />
			<outline text="围脖经典语录" 
				title="围脖经典语录" type="rss"
				htmlUrl="http://t.sina.com.cn/1646465281" 
				xmlUrl="http://medcl.net/SinaRss.aspx?uid=1646465281" />			
			<outline text="破阵子(1644022141)" 
				title="破阵子(1644022141)" type="rss"
				htmlUrl="http://t.sina.com.cn/1644022141" 
				xmlUrl="http://medcl.net/SinaRss.aspx?uid=1644022141" />			
		</outline>
		<outline text="珞珈山水" title="珞珈山水">			
			<outline text="今日十大热门话题" 
				title="今日十大热门话题" type="rss"
				htmlUrl="http://bbs.whu.edu.cn/frames.html" 
				xmlUrl="http://bbs.whu.edu.cn/rssi.php?h=1" />			
			<outline text="贴图版" 
				title="贴图版" type="rss"
				htmlUrl="http://bbs.whu.edu.cn/wForum/board.php?name=Picture" 
				xmlUrl="http://bbs.whu.edu.cn/wForum/rss.php?board=Picture&amp;ic=1" />
		</outline>
	</body>
</opml>

分析OPML文件的架构,然后方便通过程序来将它需要的信息写成此架构的文件,便于阅读器引用。 OPML文件由头部标签<head>(主要是本文件的一些注释,不影响实际的RSS订阅信息,不是太重要)和<body> (RSS阅读器提取订阅资源的全部数据来源)。在<body>节点下面有个一级的<outline>节点,这个节点对应RSS阅 读器中地RSS资源的分类文件夹相关信息(显然text表示的就是文件夹名称),然后一级<outline>下面就是二级 的<outline>标签对,这里面就是RSS资源的相关数据内容了。二级<outline>中的节点的一些重要属性:text 表示资源的标题,htmlUrl表示的是信息的的Web网页地址,xmlUrl表示的是信息的RSS订阅地址。

3. 新浪微博API――从服务器上导出用户好友数据到本 地XML文件

关于新浪微博API的详细介绍,可以参考新浪微博API官方网站:

http://open.t.sina.com.cn /wiki/index.php/首页

关于身份认证和数据请求,请参考cnblogs:

《.NET调用新浪微博开放平台接口的代码示例》

http://www.cnblogs.com/cmt/archive/2010/05/13/1733904.html

下面是自己整理的代码,从服务器上请求用户的好友信息:

private void getFriends()
        {

            int previous_cursor=-1;
            int next_cursor = -1;

            while (next_cursor != 0)
            {
                string cursor = Convert.ToString(previous_cursor);
                string url = " http://api.t.sina.com.cn/statuses/friends.xml?source=AppKey&cursor=" + cursor;
                string username = "dreamzsm@gmail.com";
                string password = name; //这里输入你自己微博登录的的密码
                //注意这里的格式哦,为 "username:password"

                System.Net.WebRequest webRequest = System.Net.WebRequest.Create(url);
                System.Net.HttpWebRequest myReq = webRequest as System.Net.HttpWebRequest;

                //身份验证
                string usernamePassword = username + ":" + password;
                CredentialCache mycache = new CredentialCache();
                mycache.Add(new Uri(url), "Basic", new NetworkCredential(username, password));
                myReq.Credentials = mycache;
                myReq.Headers.Add("Authorization", "Basic " + Convert.ToBase64String(new ASCIIEncoding().GetBytes(usernamePassword)));

                WebResponse wr = myReq.GetResponse();
                Stream receiveStream = wr.GetResponseStream();
                StreamReader reader = new StreamReader(receiveStream, Encoding.UTF8);
                string content = reader.ReadToEnd();


                XmlDocument xmlDoc = new XmlDocument();

                xmlDoc.LoadXml(content);
                // xmlDoc.Load("data1.xml");

                XmlNodeList nodeList = xmlDoc.SelectSingleNode("users").ChildNodes;//获取根节点的所有子节点

                next_cursor = Convert.ToInt16(nodeList.Item(nodeList.Count - 2).InnerText);
                previous_cursor = Convert.ToInt16(nodeList.Item(nodeList.Count-1).InnerText);



                string xmlName = "friends_" + nodeList.Item(nodeList.Count - 1).InnerText + "_" + Convert.ToInt16(nodeList.Item(nodeList.Count - 2).InnerText) + ".xml";
                previous_cursor = next_cursor;

                xmlDoc.Save(xmlName);

            }

          

        }

为了程序设计简单一点,笔者就有点偷懒了,没有仔细研究如何将所有的数据写到一个XML文件中,而是每次请求得到的20条数据写成一个XML文件, 最后我159个好友,按照指定的命名方法生成了8个XML文件。

clip_image002

如此,就得到了所有的你的好友(就是你跟随的人)的信息了,以单人为例,其主要信息如下:

<user>
    <id>1710993410</id>
    <screen_name>某丫大人</screen_name>
    <name>某丫大人</name>
    <province>43</province>
    <city>1</city>
    <location>湖南 长沙</location>
    <description>饭否儿,心朝饭否,春暖花开。 我还是@饿YA 我还真是懒得介绍了。</description>
    <url>http://1</url>
    <profile_image_url>http://tp3.sinaimg.cn/1710993410/50/1273755892</profile_image_url>
    <domain>
    </domain>
    <gender>f</gender>
    <followers_count>168</followers_count>
    <friends_count>79</friends_count>
    <statuses_count>846</statuses_count>
    <favourites_count>0</favourites_count>
    <created_at>Sun Mar 14 00:00:00 +0800 2010</created_at>
    <following>false</following>
    <verified>false</verified>
    <allow_all_act_msg>false</allow_all_act_msg>
    <geo_enabled>false</geo_enabled>
    <status>
      <created_at>Sun May 16 21:02:44 +0800 2010</created_at>
      <id>364379114</id>
      <text>烦死了快、</text>
      <source>
        <a href="">新浪微博</a>
      </source>
      <favorited>false</favorited>
      <truncated>false</truncated>
      <geo />
      <in_reply_to_status_id>
      </in_reply_to_status_id>
      <in_reply_to_user_id>
      </in_reply_to_user_id>
      <in_reply_to_screen_name>
      </in_reply_to_screen_name>
    </status>
  </user>

可以看到这里面的信息量是超级多的,我简单介绍下几个主要的节点吧

id 用户新浪微博的数字ID,就像你的QQ号一样
name 用户昵称
province 省代号
city 市代号
location 所在省市(好像和上面两个节点重复了)
description 自我描述
domain 域名,就是除了数字ID后,用户申请的修改域名
gender 性别。男的是Male,女的是Female.
followers_count 粉丝数
friends_count 跟随的人数
statuses_count 发表的状态也就是微博数
favourites_count 收藏微博数目吧?(不知道这个有什么用)
created_at 用户创建此微博客的时间
verified 是否经过新浪的VIP认证
status 用户最近的一次状态

除了user信息外,还有一些其它信息,比如根节点下的next_cursor和previous_cousor,这方便用户分多次到服务器上请求 数据时可以此作为定位依据。

<next_cursor>20</next_cursor>

<previous_cursor>0</previous_cursor>

4. 将XML文件存储到ACCESS数 据库中进行备份

如果不想备份的可以直接从第3步中到第5步,但是笔者,觉得将数据转换成此构架后,更加方便后来的程序操作以及浏览数据。

关于XML的详细方法参考:小气的鬼

在 C#.net中如何操作XML

http://www.cnblogs.com/weekzero/archive/2005/06/21/178140.html

下面开始读取刚才从新浪微博服务器上请求得到的XML文件了。然后转换成ACCESS数据库内容。(当然你要先用ACCESS在指定目录下建立一 个*.mdb文件用来存储数据)

下面是对单个XML文件进行读取,并插入到数据库中(这段代码是在ASP.NET中写的)

 public void readTsinaFriends(string fileName)
    {
        XmlDocument xmlDoc = new XmlDocument();
        xmlDoc.Load(Server.MapPath(fileName));  

       XmlNodeList nodeList = xmlDoc.SelectSingleNode("users").ChildNodes;//获取 根节点的所有子节点
       ;

        //删除不用的一级节点,比如提示人数的所在位置的标记
       XmlNode root = xmlDoc.SelectSingleNode("users");
     //  XmlNodeList xnl = xmlDoc.SelectSingleNode("Employees").ChildNodes;
       for (int k = 0; k < nodeList.Count; k++)
       {
           XmlElement xe = (XmlElement)nodeList.Item(k);
           if(xe.Name=="user")
           {//去掉XML文件中不需要的节点:next_cursor,previous_coursor以及user节点中的status,方便XML直接转换成DataTable
                XmlNodeList nodeList1 = xmlDoc.SelectNodes("users/user");//得到所有的标签user一级节点

                foreach (XmlNode xmlNodeTemp in nodeList1)
                {
                    if (xmlNodeTemp.LastChild.Name == "status")//移除每个user节点中的"status"子节点--(一般情况下此节点都放在最后一个,所以就不遍历了,直接地址定位)
                    {
                        xmlNodeTemp.RemoveChild(xmlNodeTemp.LastChild);
                    }                
                }
              
               
           }
           else if (xe.Name == "next_cursor" || xe.Name == "previous_cursor")
           {
               root.RemoveChild(xe);
               if (k < nodeList.Count) k = k - 1;
           }
       }



        string tbxml = xmlDoc.OuterXml;
        DataTable dt = new DataTable();

        DataSet ds = new DataSet();
        System.IO.StringReader reader = new System.IO.StringReader(tbxml);
        ds.ReadXml(reader);
        dt = ds.Tables[0];//如果XML文本中有同名的父子节点,那么此语句就会多读出一条数据,这可能是此API函数的局限性吧

        DataTable dtCopy = dt.Copy();
        //dtCopy.Columns.Remove("url");
        //dtCopy.Columns.Remove("profile_image_url");
        dtCopy.Columns.Remove("description"); //这个字段里面字符编码不太规则,在插入ACCESS的时候总有问题,而且用处不大,所以就去除了。(又偷懒了呃)


        DataRow drTemp = dtCopy.NewRow();
        string strInsert = string.Empty;

        OleDbConnection aConnection = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=E:\\coursware\\网络软文\\API_微波\\weibo.mdb");
        aConnection.Open();

        for (int i = 0; i < dtCopy.Rows.Count - 1; i++)
        {
            drTemp = dtCopy.Rows[i];
            strInsert = "'"+drTemp[0].ToString()+"','";
            for (int j = 1; j < dtCopy.Columns.Count - 1; j++)
            {
                strInsert += (drTemp[j].ToString() + "','");
            }
            strInsert += drTemp[dtCopy.Columns.Count - 1].ToString() + "'";
           
            string strCmd = "INSERT INTO Friends VALUES(" + strInsert + ")";

            
            OleDbCommand command = new
                OleDbCommand(strCmd, aConnection);
            command.ExecuteNonQuery();
        }
        aConnection.Close();
       
             
     
    }

对多个XML文件进行遍历,一个个导入到ACCESS数据库中:

 /// <summary>
    /// 将所有好友都导出了,然后存储在ACCESS数据库中了。
    /// </summary>
    public void readAllXml()
    {
        for (int i = 0; i < 8; i++)
        {
            string fileName = "friends_" + Convert.ToString(i * 20) + "_" + Convert.ToString(i*20+20)+".xml";//按照存储XML文件时的命名规则进行读取
            readTsinaFriends(fileName);
        }
    }

经过上面的操作后,你再打开你的ACCESS数据库文件weibo.mdb文件中对应的表,就可以看到所以的信息都已经导入到ACCESS中了。如 下图所示:

clip_image004

5. 对ACCESS数据库查询并写成RSS阅 读器的OPML格式

对于制作RSS阅读器的OPML格式,需要的数据只有两条字段:一个是id字段,一个是name字段。

这个过程实际上就是对数据进行XML编码的过程,啥都不说了,一切都在代码中了(也是在ASP.NET工程中写的):

/// <summary>
    /// 建立新浪微博的RSS文件
    /// </summary>
    public void CreateTsinaRssXmlFile()
    {

        OleDbConnection aConnection = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=E:\\coursware\\网络软文\\API_微波\\weibo.mdb");


        string strCmd = "select id as idnum,screen_name as name from Friends";
        //从ACCESS中获取数据
        aConnection.Open();
        OleDbDataAdapter da = new OleDbDataAdapter(strCmd, aConnection);
        DataSet ds = new DataSet();
        da.Fill(ds, "TSina");
        ds.DataSetName = "RssReader";
        DataTable dt = ds.Tables[0];//数据集的第0张表格


        XmlDocument xmldoc;

        XmlElement xmlelem;

        xmldoc = new XmlDocument();
        //加入XML的声明段落
        XmlDeclaration xmldecl;
        xmldecl = xmldoc.CreateXmlDeclaration("1.0", "UTF-8", null);
        xmldoc.AppendChild(xmldecl);

        //加入一个根元素
        xmlelem = xmldoc.CreateElement(" ", "opml", " ");
        xmldoc.AppendChild(xmlelem);

        XmlNode root = xmldoc.SelectSingleNode("opml");//查找<opml> 节点


        XmlElement xeHead = xmldoc.CreateElement("head");//创建一个<head>节点 
        //为head节点增加子节点
        XmlElement xeHeadsub = xmldoc.CreateElement("title");
        xeHeadsub.InnerText = "Rss Reader";//设置节点文本 
        xeHead.AppendChild(xeHeadsub);//添加到<head>子节点中 
        root.AppendChild(xeHead);//添加到<head>节点中 


        //增加body子节点,然后,将所有的RSS订阅信息全部写入到body节点中间
        XmlElement xeBody = xmldoc.CreateElement("body");
        root.AppendChild(xeBody);


        //第一层循环是标签(文件夹循环)由于本次只做一个标签,所以就只循环一次了

        //RSS的文件夹属性节点
        XmlElement xe1 = xmldoc.CreateElement("outline");
        xe1.SetAttribute("text", "Tsina");//设置该节点title属性
        xe1.SetAttribute("title", "Tsina");//设置该节点title属性 --第一层的outline节点的属性表示的是RSS的标签或者说是文件夹


        //下面就要开始为此文件夹节点添加下属子节点,也就是添加一些实质的RSS地址了
        string strTitle = string.Empty;
        string strText = string.Empty;
        string strXmlUrl = string.Empty;
        string strHtmlUrl = string.Empty;


        for (int i = 0; i < dt.Rows.Count; i++)
        {
            strTitle = dt.Rows[i]["NAME"].ToString().Trim();
            strText = strTitle;
            strXmlUrl = "http://medcl.net/SinaRss.aspx?uid=" + dt.Rows[i]["IDNum"].ToString().Trim();
            strHtmlUrl = "http://t.sina.com.cn/" + dt.Rows[i]["IDNum"].ToString().Trim();

            XmlElement xesub1 = xmldoc.CreateElement("outline");
            xesub1.SetAttribute("text", strText);//设置该节点title属性
            xesub1.SetAttribute("title", strTitle);//设置该节点title属性 --第一层的outline节点的属性表示的是RSS的标签或者说是文件夹
            xesub1.SetAttribute("type", "rss");
            xesub1.SetAttribute("xmlUrl", strXmlUrl);

            xesub1.SetAttribute("htmlUrl", strHtmlUrl);
            xe1.AppendChild(xesub1);//添加到<Node>节点中 
        }
        xeBody.AppendChild(xe1);


        //保存创建好的XML文档
        xmldoc.Save(Server.MapPath("RssReader.xml"));

    }

最后在指定的目录下,程序就自动生成了一个RssReader.xml的文件了。大功告成了!

clip_image006

然后将此文件就可以导入到任何一个RSS阅读器中了,用户就能够通过RSS阅读器来获取微博信息了,而且现在的RSS阅读器都有个一键转贴到微博的 功能,很方便的,不想转到自己微博的,也可以通过RSS阅读器直接收藏到阅读器中。辛苦了两天,今天能有这么一点小成果,还是觉得很不错的,呵呵,也祝大 家也能好运。本次代码比较还需要各种完善,比如,如何将所以的数据写成一个XML文件,这个笔者就暂时不做了,留给大家去做吧。

Rss阅读器效果图如下:

clip_image008

后记:新浪微博开放了API,从此新浪微博的可玩性就变强了很多了。写下本文主要是为了抛砖引玉,其实还有很多其它功能笔者想实现,但现在因为毕业 在即,还要忙毕业设计,所以希望大家可以试试,比如利用API来备份用户发的微博等等。

最后也写上本人的微博地址吧,如果有何指教,请留言:http://t.sina.com.cn/fly4u

———————————————–

Author:一点一滴的Beer

Email /Gtalk:dreamzsm@gmail.com

From:http://www.cnblogs.com/beer

Notes:欢迎转贴,但请在页面中加个链接注明出处,就当是对作者的一点小鼓励吧^_^

Time:2010-5-17

作者:一点一滴的Beer
出处:http://www.cnblogs.com/beer/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,请尊重作者的劳动成果。

[转载]程序员这碗饭

mikel阅读(1189)

[转载]程序员这碗饭 – Lau Yee .Net – 博客园.

出来混,无非为一个“钱”。

别给我强调你有多么的喜欢这个行业,有多么的喜欢写代码,有多么的喜欢钻研新的技术。做为一个深爱技术的老程序员,我和你一样。但浅意识里你衡量最多的还 是那个字。

已经有太多的人被忽悠近来(强烈鄙视略质培训机构),如果你近来看这篇文 章,我很不幸的告诉你,你也认为这碗饭不好吃了。你是否幻想过,有诏一天你能写出一个伟大的作品、某一天你会成为一个行业专家、某一天一回是一个领域的顶 尖高手,受万人景仰,靠此腰缠万贯。但现在你开始怀疑了。也许你比我看得开点,做这行只是因为待遇还可以,还能混口饭吃。我猜你是第一种,你肯定是那种喜 欢思考的程序员。因为混很容易,但是要混得出色,就必须要思考。令我矛盾的是这两种想法我都有。我只能极力的不将自己归为混日子的那种。你也认为应该坚持 吗?

时不如前,人一天天的老去,一天瞎忙火,却始终不明白为什么?

人总要为自己考虑。以前花费了太多的时间沉迷于技术,宁愿去做苦力而不是去享受温柔。也能这是我的最求,但却不是我最求的生活?我本末倒置,忘了实现美好 生活和实现人生价值的等级。

说起来真是老不如新,大多新人都很清楚自己在做什么,他们有理想有盲目的职业规划,但这感觉很好。他们会幻想他们的职业生涯。什么软件开发、项目管理、系 统设计是很美好的,有那一车一车的书教他们应该怎么去做。他们知道只要把这些东西看完、熟悉了他们便是专家高手。直到他们产生怀疑,直到他们发现教他们的 人其实比他们还迷茫。到那时他便也成了老人了。为什么现在我们放慢了我们的脚步,不再像以前一样执著、有朝气。

我们不期待已此改变人生,只希望活得滋润一些,爽一些。在翻开很久前的计划,在里面加上“钱”,根据实际情况,从新的制定,认真地执行它。

有些前辈们教导我们不可沉湎于技术,如果你的心思全部放在这上面,那么注定你将成为孔乙己一类的人物!除非你愿意60岁还在写代码。呵呵,就我来说,事实 上我愿意。不管到时候称呼是什么、职位是什么,我仍喜欢写程序。但要活的更滋润一些,那么就适可而止为之,技术只不过是你今后前途的支柱之一,而且还不是 最大的支柱。你如果能看出我的矛盾,就不要一样不可救药。

计划的第一步是选定一个课题(呵呵,还好这个已经完成了),然后围绕他但是不能局限它,而对此进行深入的学习实践。我说的围绕不局限于技术。以前我总是不 明白,时常瞧不起某人,说他“什么都不懂,凭啥拿那么多钱,凭啥升官!”,但后来我不得不承认,人家的综合能力的却有我所不及之处,有时候人家的几句话, 就能顶上我们的几百行代码。所以一定要培养自己多方面的能力,包括管理,亲和力,察言观色能力,攻关能力等,要成为综合素质的高手,则前途无量,否则只能 躲在角落看显示器!技术以外的技能才是更重要的本事!!

以前总是懒得说、懒得写。让别人还以为你自命清高,难以交流。这样别人怎么认识你,你怎么能有更广的涉足。所以从现在开始就要多说、多写。多与人沟通。为 了技术和同行沟通。为了思路和业内人士沟通。为了解决方案和同事沟通,为了钱要善于在领导面前表达自己的观点。我不介意你明天就去给领导谈给你加薪的事 情,不要抹不下脸。这也是中磨练。要是你有什么其他的想法可以详详细细的把它写下来,发Email给领导。即使这次不成功,也会在他心里种下一些种子。

也许哪里的饭都不好吃,也许是大多数人都太浮躁了。要静下心了。如果你始终不能静下心的话,那我恭喜你,也应该考虑自己当老板了。在这条路上你已经比我多 走了一步。如果不幸没有成功,那更恭喜你,你比我更近了两步了,至少为下一次冲击积累了经验,不干永远没出息,而且要干成必然要经历失败。不经历风雨,怎 么见彩虹,没有人能随随便便成功!

[转载]C#动态创建和动态使用程序集、类、方法、字段等(一)

mikel阅读(972)

[转载]C#动态创建和动态使用程序集、类、方法、字段等(一) – longgel – 博客园.

有时候在整个项目架构里也需要动态创建程序集的需求,那如何创建程序集呢,请跟我来学习一下吧。

首先需要知道动态创建这些类型是使用的一些什么技术呢?其实只要相关动态加载程序集呀,类呀,都是使用反射,那么动态创建也一样使用的是反射, 是属于反射的技术!也就是将对象或者数据映射成一个对象或者程序集保存起来而已。

首先我们需要了解每个动态类型在.net中都是用什么类型来表示的。

程序集:System.Reflection.Emit.AssemblyBuilder(定义并表 示动态程序集)

构造函 数:System.Reflection.Emit.ConstructorBuilder(定义并表示动态类的构造函数)

自定义属 性:System.Reflection.Emit.CustomAttributeBuilder(帮助生成自定义属性 使用构造函数传递的参数来生成类的属性)

枚举:System.Reflection.Emit.EnumBuilder(说明并表示枚举类 型)

事件:System.Reflection.Emit.EventBuilder(定义类的事件)

字段:System.Reflection.Emit.FieldBuilder(定义并表示字段。 无法继承此类)

局部变量:System.Reflection.Emit.LocalBuilder(表示方法或构 造函数内的局部变量)

方法:System.Reflection.Emit.MethodBuilder(定义并表示动态 类的方法(或构造函数))

模块:System.Reflection.Emit.ModuleBuilder(定义和表示动态 程序集中的模块)

参数:System.Reflection.Emit.ParameterBuilder(创建或关 联参数信息 如:方法参数,事件参数等)

属性:System.Reflection.Emit.PropertyBuilder(定义类型的 属性 (Property))

类:System.Reflection.Emit.TypeBuilder(在运行时定义并创建类 的新实例)

我们有了这些类型,基本上就可以动态创建我们的任何需要使用的类型,当然很多可以动态创建的类型我不可能都介绍完,如果在项目中有需要可以去查 阅MSDN,里面都有DEMO的,主要的问题就是要理解每一种类型的定义,比如:程序集加载是靠AppDomain,程序集里包含多个模块,模块里可以声 明类,类里可以创建方法、属性、字段。方法需要在类中才可以创建的,局部变量是声明在方法体内等等规则。看MSDN就非常容易弄懂了。

1.如何动态创建它们了

AppDomain:应用程序域(由 AppDomain 对象表示)为执行托管代码提供隔离、卸载和安全边界。AppDomain同时可以载入多个程序集,共同来实现功能。

程序集:简单来说就是一个以公共语言运行库(CLR)为宿主的、版本化的、自描述的二进制文件。(说明:定义来自C#与.NET3.5高级程序设计 (第四版))

模块:类似于以前的单元,用于分割不同的类和类型,以及资源(resource, 资源记录就是字符串,图象以及其它数据,他们只在需要的时候才会被调入内存)。类型的Meta信息也是模块的一部分。多个模块组建成一个程序集。

所谓动态就是在程序运行时,动态的创建和使用。

直接看代码吧,其实超级简单。

//动态创建程序集
AssemblyName DemoName = new AssemblyName(DynamicAssembly);
AssemblyBuilder dynamicAssembly
= AppDomain.CurrentDomain.DefineDynamicAssembly(DemoName, AssemblyBuilderAccess.RunAndSave);
//动态创建模块
ModuleBuilder mb = dynamicAssembly.DefineDynamicModule(DemoName.Name, DemoName.Name + .dll);
//动态创建类MyClass
TypeBuilder tb = mb.DefineType(MyClass, TypeAttributes.Public);
//动态创建字段
FieldBuilder fb = tb.DefineField(“”, typeof(System.String), FieldAttributes.Private);
//动态创建构造函数
Type[] clorType = new Type[] { typeof(System.String) };
ConstructorBuilder cb1
= tb.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, clorType);
//生成指令
ILGenerator ilg = cb1.GetILGenerator();//生成 Microsoft 中间语言 (MSIL) 指令
ilg.Emit(OpCodes.Ldarg_0);
ilg.Emit(OpCodes.Call,
typeof(object).GetConstructor(Type.EmptyTypes));
ilg.Emit(OpCodes.Ldarg_0);
ilg.Emit(OpCodes.Ldarg_1);
ilg.Emit(OpCodes.Stfld, fb);
ilg.Emit(OpCodes.Ret);
//动态创建属性
PropertyBuilder pb = tb.DefineProperty(MyProperty, PropertyAttributes.HasDefault, typeof(string), null);
//动态创建方法
MethodAttributes getSetAttr = MethodAttributes.Public | MethodAttributes.SpecialName;
MethodBuilder myMethod
= tb.DefineMethod(get_Property, getSetAttr, typeof(string), Type.EmptyTypes);
//生成指令
ILGenerator numberGetIL = myMethod.GetILGenerator();
numberGetIL.Emit(OpCodes.Ldarg_0);
numberGetIL.Emit(OpCodes.Ldfld, fb);
numberGetIL.Emit(OpCodes.Ret);
//保存动态创建的程序集
dynamicAssembly.Save(DemoName.Name + .dll);

这一节讲了如何创建动态程序集、类、构造函数、方法、属性等,另外保存程序集,下一节就来讲如何使用创建的程序集以及MSIL指令。

[转载]PowerDesigner将PDM导出生成WORD文档

mikel阅读(1647)

[转载]PowerDesigner将PDM导出生成WORD文档–温习老知识 – 波哥###从理论到实践,从实践到抽象,从抽象到通俗,从通俗到理论 – 博客园.

今天的温习老知识,是如何将一个PD设计的PDM来导出WORD文档,这是一个非常实用的功能,可以在软件过程的数据库设计文档编写中节省N多时 间,

那不废话了,我们就开始今天的讲解吧!

第一步,点击Report Temlates 制作模板

第二步,时间问题,我们在PATH小图标中 ,选择我们已经做好的一个FDATemplate 模板,并双击,没有模版的朋友,点New图标

这时候,我们左右2个区,Aavailable区域中选择你想要在WORD文档中展示的东东,这里我们选择List of Tables,和List of Table Columns[数据表格信息]

如图,右键点击,Selection

选择你想要在数据表格中展示的信息,想要展示的就打钩

鼠标右键选择LAYOUT样式功能

制作样式

点击保存,一个简单的RTP文档就制作完成了。

接着,我们导出WORD文档

在点击OK按钮之后,就会产生我们期待已久的,WORD文档了

I List of tables

Name

Code

FDACaseAccept

FDACaseAccept

FDACaseAcceptDeal

FDACaseAcceptDeal

FDACaseAcceptRevert

FDACaseAcceptRevert

FDACaseCategory

FDACaseCategory

FDACaseDocumentMonitor

FDACaseDocumentMonitor

FDACaseReason

FDACaseReason

FDACaseSources

FDACaseSources

FDACaseSourcesWay

FDACaseSourcesWay

FDACaseSuspectMoney

FDACaseSuspectMoney

II FDACaseAccept

Code

Comment

Data Type

Mandatory

Default

Primary

Foreign Key

AcceptCodeID

案件编码

varchar(15)

FALSE

FALSE

FALSE

AcceptId

ID主键

numeric

TRUE

TRUE

FALSE

AcceptUserID

受理人ID

int

FALSE

FALSE

FALSE

AcceptUserName

受理人姓名

varchar(50)

FALSE

FALSE

FALSE

AchieveDate

datetime

FALSE

FALSE

FALSE

ByComplaintAddress

被投诉方地址

varchar(100)

FALSE

FALSE

FALSE

ByComplaintEntCode

被投诉方企业代码

varchar(50)

FALSE

FALSE

FALSE

ByComplaintEntName

被投诉方企业名称

varchar(50)

FALSE

FALSE

FALSE

ByComplaintPhone

被投诉方电话

varchar(100)

FALSE

FALSE

FALSE

ByComplaintUserName

被投诉方姓名

varchar(30)

FALSE

FALSE

FALSE

CaseCategoryId

受理类别[外键]

int

FALSE

FALSE

FALSE

CaseDate

datetime

FALSE

FALSE

FALSE

CaseSourceId

案件来源[外键]

int

FALSE

FALSE

FALSE

CaseSourceWayId

来源方式[外键]

int

FALSE

FALSE

FALSE

CaseTag

int

FALSE

~(0)~

FALSE

FALSE

CheckTypekind

int

FALSE

~(0)~

FALSE

FALSE

如果选择Generate HTML 选项,则会产生HTML版本的数据库设计

O了,就这么简单,这让我想起了一句话,科技确定生产力。

随便带2个PD的小技巧:

在Columns中加入自己需要的列:

点击:Customize columns and Filter 后

选择自己需要的属性。。

第二个,控制ENTITY的样式

点击后如图:

Limit 就是防止长字段实体的。。

[转载]InfoQ: MonoTouch:用.NET开发iPhone应用

mikel阅读(1093)

[转载]InfoQ: MonoTouch:用.NET开发iPhone应用.

引言

直到最近,要为苹果的iPhone开发应用程序的唯一选择就是一头扎进苹果的开发系统中。这意味着,你必须“愿意”在XCode IDE中编写Objective-C代码。对于很多开发人员,学习Objective-C被看作是一个巨大的障碍。特别对于哪些从来不用担心内存管理、指 针和C语言要负责处理的东西的开发人员来说,更是如此。

随着MonoTouch框架(Novell的Mono Project的一部分)的出现,这一切都将改变。Mono Project是微软.NET平台的开源实现。其允许你在几乎任何平台上运行.NET应用程序,包括Apple、FreeBSD、Linux、Unix等 等。MonoTouch是Mono Project的新组成部分,让你能够用C#和.NET平台编写可以运行在iPhone上的应用程序。

本篇文章的目的,就是提供MonoTouch平台的一个完整介绍,让大家知道到那里获取必要的工具,MonoTouch有什么样的限制,以及如何构 建一个简单的应用程序。

背景和限制

对于打算为iPhone开发应用的.NET开发人员而言,MonoTouch的出现无疑是一件好事。然而,在决定创建应用程序之前,有一些限制和背 景知识需要先了解清楚。

它如何工作?

在创建MonoTouch应用程序的时候,大部分非UI方面的.NET 3.5功能依旧可用,或者一些还处于计划之中(如.NET 4.0的功能)也囊括其中。这让你可以使用很多业已熟悉的.NET Framework技术来编写应用程序,包括Windows Communication Framework (WCF)、Workflow Foundation (WF)等等。也包括几乎所有的基类库(Base Class Library,BCL),涵盖诸如垃圾收集(Garbage Collection)、线程、数学函数、System.Net、加密等。对于可用的标准.NET程序集列表,见http://monotouch.net/Documentation/Assemblies。 MonoTouch是一种基础.NET函数库的特别定制版本,这也类似Silverlight和Moonlight的实现方式。

这意味着,你能够使用MonoTouch的核心程序集来编译标准的.NET 3.5代码成相应的函数库,并在你的应用程序中使用它们。因此,如果你有一个用于其它应用程序的特别函数库,其包含着一些用于工程问题的高级数学函数,那 么只需简单地把这些代码库加入到你的MonoTouch解决方案中,并引用它。在你构建解决方案的时候,编译器就利用MonoTouch核心函数库对其进 行编译,接着就能在iPhone应用程序中使用它了。

MonoTouch也包括一些原生iPhone API的包装函数库,如访问位置(Location,GPS)、加速计、地址簿等的函数。MonoTouch也提供相应的功能,让你能够调用那些尚未进行 包装的原生Objective-C函数库,所以你可以直接和现存的Objective-C代码进行互操作。

我如何创建用户界面(UI),我能使用Silverlight吗?

MonoTouch应用程序的UI需要使用苹果的Interface Builder(界面创建器,IB)应用程序来创建,IB连同iPhone SDK一起提供。Interface Builder使用Cocoa Touch(苹果用于iPhone的UI框架)控件对象,这些控件对象在iPhone上原生提供的。这意味着,你能在应用程序中使用所有的标准 iPhone控件,如选择器(Pickers)、滑动条(Sliders)、按钮等等。

你也能通过代码来创建界面,即实例化Cocoa Touch对象后,把它们添加到应用程序的视图(Views)中(关于视图,后面会详细讲述)。

然而,你不能利用传统的.NET技术,如Silverlight、WPF、WinForms等来创建MonoTouch界面。

Cocoa Touch使用一种融合了MVC(Model View Controller)模式思想的结构,我们将在后面一篇文章中介绍。

我如何分发我的应用?

MonoTouch应用程序的分发完全和传统iPhone应用程序的分发一样,既可以通过苹果App Store,也可以通过企业部署。

App Store是一个在线资源库,让用户可以付费购买(如果不是免费的话)和下载应用程序。可以从iTunes中访问,或直接通过iPhone本身来访问。为 了得到通过App Store分发应用的许可,你必须向苹果注册,并支付每年99美元的年费。

企业部署方式就是为公司开发内部应用程序,并分发给员工等人员使用,无需把应用在App Store中列出。

什么是许可模型?

不像Mono那样,MonoTouch不是开源的,且是一个收费产品。这意味着,如果你打算开发一些实际的应用,就必须购买软件许可。

  • 专业版($399)——单个的个人开发人员许可,让你可以开发应用程序,并通过苹果App Store来分发它们。
  • 企业版($999)——单个的企业开发人员许可,让你可以开发应用程序,并通过苹果App Store来分发它们,或者进行企业部署。
  • 企业版,5人($3999)——和企业版一样,只是提供了5个坐席的授权。

以上所有选项都包括了一年的免费升级权益。

还有一个评估版本,你只能把应用部署到模拟器中。出于介绍的目的,我们只需要评估版本就行。

MonoTouch有哪些限制?

没有即时(JIT)编译

根据苹果的iPhone政策,任何应用程序都不能包含需要JIT编译的代码。但是稍等,.NET确实能正确工作,是不?对,不过MonoTouch 是通过把应用程序编译为原生的iPhone程序集来跳过这个限制的。但是,这也带来了几个限制。

  • 泛型——泛型是由JIT编译器在运行时进行实例化的,然而,Mono具备一种提前(Ahead of Time ,AOT)编译的模式,可以为类似List<T>这样的泛型集合生成方法和属性。而泛型的其他用法,例如泛型虚方法、泛型类型上的 P/Invokes和Dictionary<TKey, TValue>上的值类型,就不被支持(虽然存在Dictionary<TKey, TValue>的代替方法)。
  • 动态代码生成——因为动态代码生成依赖于JIT编译器,所以对任何动态语言编译的过程也不能支持。包 括System.Reflection.Emit、 Remoting和动态语言运行时(DLR)。

C#是唯一的语言

另外,目前用于编写MonoTouch应用程序的唯一可用语言是C#。Visual Basic.NET有望在MonoTouch未来的发布中支持,不过此时此刻我们别无选择。

更多信息

相关限制的完整列表和更多的信息,包括一些代替方法,可用参见http://monotouch.net/Documentation/Limitations

入门

要进入为iPhone创建MonoTouch应用程序的大门,我们需要下面几样东西:

  • 一个使用Intel CPU的Mac电脑,其要安装MacOSX 10.5或10.6 (Leopard或Snow Leopard)
  • 苹果的iPhone SDK 3.0或更高版本
  • Mono的当前版本
  • MonoTouch SDK
  • 一个IDE工具,如MonoDevelop或XCode,或一个文本编辑器程序

安装着Leopard或Snow Leopard的Mac

这是最重要也是最容易忽视的需求。尽管,理论上你能在任何平台上开发大部分应用程序,然而iPhone Simulator和Interface Builder只能在Leopard和Snow Leopard上运行。另外,编译器本身用到了一些特定于Intel Mac机器的底层功能,所以购买这样一台电脑是绝对必须的。

苹果的iPhone SDK

iPhone SDK可通过http://developer.apple.com/iphone/来 免费下载,不过必须在苹果网站上注册,才能访问这个地址。

在安装了iPhone SDK后,要确保你能正常启动iPhone Simulator。要启动它,只需打开Spotlight,键入iPhone Simulator。

Mono

一旦你测试iPhone Simulator正常,那么就要安装Mono for OSX的最新版。Mono可以从http://mono-project.com/Downloads下 载。记住要点击“Intel”版本的链接,不要点CSDK版本。同样,安装MonoTouch SDK之前也需要安装Mono的。Mono的安装包是磁盘镜像的形式,挂接镜像,双击安装包,根据安装向导完成安装过程。

MonoTouch SDK

接下来,下载和安装最新的MonoTouch SDK。你既可以在MonoTouch商店(http://monotouch.net/Store)购买,购买后会 收到一个下载链接,也可以从http://monotouch.net/DownloadTrial下 载评估版。如果购买了MonoTouch,你就能把应用程序部署到一台正确配置了的iPhone上,不过也可像我这样,仅仅在模拟器中运行。所以,目前 而言试用/评估版就足够了。

文本编辑器或集成开发环境(IDE)

如果你打算创建MonoTouch应用程序,所需的所有东西就是前面提及的,和一个文本编辑器。你能创建所有代码文件,并用命令行(终端窗口)来手 动编 译。这种方式虽然可行,但是实际操作起来可能会非常痛苦,所以我们还是需要使用一个IDE来开发我们的应用程序。

你可以编辑/hack一下XCode(随iPhone SDK一起安装)来利用MonoTouch的函数库和编译器,也可以使用MonoTouch版的MonoDevelop,其已经为MonoTouch应用 程序做好所有配置了。我们理所当然要用MonoDevelop,所以访问这里http://monodevelop.com/Download/Mac_MonoTouch来 下载它。要安装MonoDevelop,只用把下载文件拖到应用程序目录中就行。

如果你已经正确安装Mono,那么MonoDevelop应该可以正常启动。

Hello World应用程序

现在,一切已经准备妥当,让我们开始来尝试开发点东西了。

MonoDevelop

首先,启动MonoDevelop。你应该会看到和下图类似的界面【译者注:如果OSX的首选语言是中文的话,MonoDevelop的菜单和工具 栏的文字显示不正常,所以最好把English拖到语言选项的第一位】:

作为一个标准的IDE,看上去还是蛮熟悉的。它非常类似Visual Studio、SharpDevelop、Visual C# Express等等。

我们创建一个新解决方案,来包含iPhone项目。这里的解决方案和Visual Studio中的概念一样,实际上你可以在MonoDevelop中打开Visual Studio创建的解决方案。在MonoDevelop中的一个不同点就是,你能够在一个MonoDevelop实例中打开多个解决方案,正如下面的截图 所示:

这完全是由于在OSX中,你不能启动MonoDevelop的多个实例(事实上,任何程序都不行),且没有任何变通方法。所以,如果你需要在解决方 案间切 换(例如,你希望另外打开一个包含示例代码的解决方案),你就能简单地一次性打开多个。

那么,说了上面这么多,让我们现在来创建一个解决方案吧。在菜单中,点File:New:Solution:

我们要创建一个如下面截图所示的“iPhone MonoTouch Project”。选中它,并命名为Example_HelloWorld_1。

这里再次和Visual Studio中创建新解决方案的对话框很类似。点击Forward ,显示下一屏,直接点击OK,因为我们不需要这些功能:

你现在应该可以看到如下所示的解决方案视图了(注意,我展开了解决方案中的节点,以便显示出所有文件和引用程序集):

我们来过一遍这些东西:

  • References ——这个文件夹包含MonoTouch应用程序需要的基本引用。MonoTouch程序集包括特定于iPhone的任何东西,也包括了所有Cocoa Touch控件的包装器,以及类似位置、数据等核心iPhone接口。以System.开头的程序集是.NET的基类库和运行时,其被裁减过以便能运行在 iPhone上。
  • Main.cs ——这和控制台应用程序、WPF应用程序等是一致的。在这里调用的是static void main() ,其是作为应用程序的入口点。过一下我们会仔细研究一下这个文件。
  • MainWindow.xib和MainWindow.xib.designer.cs ——这个和Winforms Window或WPF Window类似。xib文件实际上要在Interface Builder中进行编辑,而designer.cs文件包含这个窗体的属性。

让我们来仔细研究一下Main.cs文件中的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using MonoTouch.Foundation;
using MonoTouch.UIKit;

namespace Example_HelloWorld_1
{
	public class Application
	{
		static void Main (string[] args)
		{
			UIApplication.Main (args);
		}
	}

	// The name AppDelegate is referenced in the MainWindow.xib file.

	public partial class AppDelegate : UIApplicationDelegate
	{
		// This method is invoked when the application has loaded its UI and its ready to run
		public override bool FinishedLaunching (UIApplication app, NSDictionary options)
		{
			// If you have defined a view, add it here:
			// window.AddSubview (navigationController.View);			

			window.MakeKeyAndVisible ();			

			return true;
		}

		// This method is required in iPhoneOS 3.0
		public override void OnActivated (UIApplication application)
		{
		}
	}
}

其中有两个有趣的地方。它包含一个Application类和一个AppDelegate类。从这里开始,和传统的.NET GUI开发就有所不同了。

iPhone应用程序的工作方式是,应用程序类(继承于UIApplication)包含了所有窗口、视图、控件和资源等等;同时应用程序委托类中 (继承于UIApplicationDelegate)处理来自iPhone OS的回调,实际上会包括应用程序运行周期(Lifecycle)的事件(例如应用程序启动和应用程序终止)和大量的运行时事件(例如低内存报警)。

通过在应用程序委托类处理这些事件,你就能够响应它们。比如,在应用程序关闭的时候,WillTerminate()方 法将被调用,这样就有机会去保存任何用户数据、应用程序状态等。

在Application类中,具有一个Main() 方法。调用UIApplication.Main,Objective-C运行时将查找MainWindow.xib文件(它包含了 UIApplicationDelegate类的名称),实例化Application类(为单实例)后,就接着调用AppDelegate类中运行周期 事件。

你不必把主窗体的名称命名为“MainWindow.xib” (即所谓的主界面文件)。你可以任意命名它,只需告知编译系统去查找哪个文件就行。如果你希望它去查找不同的文件,在项目文件上右键打开项目选项,点击 Options ,接着在Build : iPhone Application : Main Interface File中即可设置主窗体对应的文件。在应用程序启动的时候,Objective-C运行时将会尝试去加载那个文件,并根据这个文件内的设置来查找应用程 序委托类。

另外,你也可以任意命名你的应用程序委托类。默认情况下,它的名称为“AppDelegate”。要改变它,在Interface Builder中打开主界面文件,修改Application Delegate的名称。

一会我们会回到Main.cs文件上来,不过首先来深入研究下应用程序的实际GUI。

Interface Builder

目前为止,已经读到了我们的iPhone应用程序的部分代码,可以深入研究一下如何构建它的界面了。苹果的应用程序设计工具包称之为 Interface Builder。Interface Builder可以和开发环境松耦合。它可以编辑那些定义应用程序GUI的.xib文件。NIB和XIB的比较:Nib文件包含了窗口、控件等的XML表 示,类似于WPF/Silverlight中的XAML模型。

不管是在XCode中编写Objective-C,或在MonoDevelop中编写C#,Interface Builder的用法都是完全一样的。能这样,完全是因为MonoDevelop能够监测Nib文件的变更,并添加/删除对应于Nib文件的适当代码到 designer.cs文件中。

你当然可以不打开Interface Builder,纯粹通过编程来创建整个GUI,有些开发人员确实也是这样做的。很多事情在Interface Builder也无法完成,就此而言,你还是需要编程来完成某些事情。Interface Builder隐藏了一些复杂的部分,在入门的时候,很容易使用Interface Builder来熟悉iPhone应用程序GUI的一些概念。

那么,说了这么多,让我们来着手创建界面了。在MainWindow.xib文件上双击。Interface Builder将启动,并能看到如下图所示的东西:

让我们逐一研究一下这些窗口。从左到右,分别是:Document Window(文档窗口)、Design Surface Window(设计界面窗口)、Library Window(控件库窗口)和Inspector Window(检查器窗口)。

首先让我们来看Document Window:

这个窗口显示了在.xib文件中的所有对象。这是默认的视图,你会发现它虽然样子漂亮,但没有太大用处,因为你的对象实际上是层级排列的,而图标视 图只能同时显示一级。在我们添加控件到界面上的时候,它不会显示在这个视图中。所以,我们需要通过点击View Mode工具条上中间的图标来改变列表视图。改变后,应该会显示如下的样子:

下一个窗口是设计界面。也就是,我们实际拖拽Cocoa Touch控件来设计我们界面的地方:

当然,由于我们尚未添加任何控件到上面,所以现在还是一片空白。

下一个窗口是Library。Library包含了所有能在设计界面上使用的Cocoa Touch控件。如果你运行Leopard【译者注:原文这里为Snow Leopard,实际是错误的。】,那么你的控件库窗口如下所示:

如果你运行Snow Leopard【译者注:原文这里未Leopard,实际是错误的。】,它应该是这个样子:

注意它们两者还是非常类似的。在Snow Leopard里,有一个名为“Classes”的标签页,我们后面会讲到这个东西,不过这也是唯一的不同点。

这是Library的默认视图,不过我喜欢稍微不同的样子,以便我能一下看到更多的控件。为了改变Library窗口中的视图,右键点击控件视图, 可以选择不同的显示风格。你也可以点击窗口左下角的Gear(齿轮)按钮。下图是Leopard中的“icons and labels”风格:

而在Snow Leopard中是:

最后一个窗口是Inspector Window:

Inspector具有四种不同的视图,可以通过窗口顶部的标签栏来选择。这些视图分别是Attribute Inspector、Connections Inspector、Size Inspector和Identity Inspector。Inspector大致和Visual Studio中的Property Explorer类似。它向你显示当前选中的Cocoa Touch对象的所有属性。也可以用它来设置可视化属性、布局等等。在创建Outlets和Actions时也用得着它,这个主题后面会谈到。在下面的图 片中,我们在Document窗口中选择了Window对象,所以我们可以查看这个对象的相关属性。

现在,我们对Interface Builder窗口已经大致浏览了一遍,接下来让我们实际地创建一些东西。我们要创建如下这样的界面:

首先,拖一个“Round Rect Button(圆角矩形按钮)”(UIButton)到窗口上。接着,在按钮上双击来设置文本。在这个过程中你会注意到,你会获得少许的指导。这些指导是 基于苹果的人机交互向导(Human Interface Guidelines)的,来辅助你在视图上以适合的间距等来定位控件。

在窗口上添加了按钮后,拖入一个“Label(标签)”(UILabel)控件。改变它的尺寸以便接近窗口的宽度。接着双击这个label控件,删 除文本以使应用程序启动的时候,标签的内容是空白的。

如果你正确地完成了所有步骤,那么你的Document Window将显示如下的样子(点击“Window”旁边的箭头就会看到它包含的子控件):

我们现在创建了第一个窗口界面。不过,不像传统的.NET GUI开发,你还不能编程访问这些控件。假如这是一个WPF应用程序,你一拖动控件到设计界面上,你就能通过this.ControlName这样的形式 来访问它。如果你马上去查看MainWindow.designer.cs文件,除了“window”属性外,你看不到任何其他代码。为了让这些对象能被 代码访问,我们必须通过Outlets把它们关联上。你在Interface Builder中创建一个Outlet(对象关联口)的时候,MonoDevelop将在这个类的designer.cs文件中添加一个匹配的属性,让你 可以编程访问这些控件。

Outlets(对象关联口)

我们来为之前添加的标签和按钮控件添加outlets,以便能在代码中访问它们。这点在Leopard和Snow Leopard上也有所区别,所以大家要严格遵循这里提到的正确指示。

【SNOW LEOPARD指示开始】

确保Library Window是打开的。点击顶部的“Classes”标签。点击第一个下拉列表框,这个就是所谓的“Library”,滚动到最后选择“Other Classes”。就会显示在你的项目中存在的自定义类。从上面列表中选择AppDelegate,接着选择下面的“Outlets”标签:

点击“+”按钮两次来创建两个新的Outlet。

【SNOW LEOPARD指示结束】

【LEOPARD指示开始】

首先,保证在Document Window中App Delegate是被选中的。如果App Delegate未被选中,那么在创建Outlets的时候,它们的属性不会被创建,或者会在错误的地方创建。

接下来,来看Identity Inspector。Identity Inspector是Inspector窗口的最后一个标签页。现在,在Identity Inspector中定位到“Class Outlets”部分。在Class Outlets上,点击“+”按钮两次来创建两个新的Outlet。

【LEOPARD指示结束】

每个outlet都具有一个名称和一个类型。名称代表了控件属性的名字,这个类似于ASP.NET的ID,或WPF中的Name。类型是 Outlet的实际类型,比如UIButton、UILabel、UITextView等等。为了命名它们,在它们的名称上双击,键入相应的名称。对于我 们之前添加的outlet来说,我们修改为“btnClickMe”和“lblResult”。

目前,它们两者的类型都是“id”。如果你不改变类型,就能把它们挂接到任何东西上,因为id就意味着动态类型,本质上就是.NET世界中的 “object”。id类型虽然好,不过我们打算把它们改为实际的类型。过一会我们会看到这样做会有什么不同。现在,双击btnClickMe的类型,键 入“UIButton”。你的Class Outlets 窗口应该显示如下这个样子:

如果在里面没有window的outlet,意味着你没有在App Delegate创建outlet。如果这样的话,删除Outlets,保证在Document Window中选中App Delegate,重新创建outlets。

现在我们已经创建了这些outlets了,就需要实际地把它们关联到我们的控件上。首先,在Inspector窗口上点击第二个标签页,来选中 Connections Inspector。在Outlets部分,应该可以看到我们之前创建的两个Outlets了。然而,你不能把它挂接到任何东西上。注 意,“window”这个outlet已经挂接到“Window”对象上了。

为了挂接我们的Outlets,我们要从“Outlets”中的outlet圆点上,拖动到我们想要挂接的控件上。在这样做的时候,我们将会看到如 下所示的效果:

对两个Outlet都进行这样处理。你也可以从Connections Inspector拖到Document Window上。如果控件相互重叠的情况下,这样就很有用。下面的截图就描述了这种方式:

在我们这样做的时候,你可能会注意到一些有趣的事情。因为设置lblResult的类型为UILabel,所以在我们把它的 Outlet拖到Window的时候,它只允许我们挂接到那些类型一致的控件上,在这个例子中就是UILabel。另外一方面,btnClickMe能被 拖到任何东西上,因为它具有动态的ID类型。这就是我们要设置强类型outlet的一个原因,以便降低它挂接到错误控件上的可能性。当然,这不是必须的, 不过这样做是一个良好的习惯。

好的,现在我们创建好了界面了,outlets也挂接好了,让我们回到MonoDevelop把一起串在一起。

回到MonoDevelop

如果你打开MainWindow.designer.cs,在其中会到两个属性:

[MonoTouch.Foundation.Connect("btnClickMe")]

private MonoTouch.UIKit.UIButton btnClickMe {
	get {
		return ((MonoTouch.UIKit.UIButton)(this.GetNativeField("btnClickMe")));
	}
	set {
		this.SetNativeField("btnClickMe", value);
	}
}

[MonoTouch.Foundation.Connect("lblResult")]

private MonoTouch.UIKit.UILabel lblResult {
	get {
		return ((MonoTouch.UIKit.UILabel)(this.GetNativeField("lblResult")));
	}

	set {
		this.SetNativeField("lblResult", value);
	}
}

有了这两个属性,就可以让我们通过代码来访问标签和按钮了。在这里要注意一件有趣的事情——就算我们声明btnClickMe的类型为 id,而自动创建出来的属性也是强类型的UIButton。这是因为MonoDevelop足够智能,可以查看outlet背后实际的类型,以便创建适合 类型的属性。这对于我们很有用,因为意味着我们在每次使用它的时候,都无需把btnClickMe属性转换为UIButton类型。

现在回到Main.cs文件,查看AppDelegate。我们来看一下FinishedLaunching方法。

// This method is invoked when the application has loaded its UI and its ready to run

public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
	// If you have defined a view, add it here:
	// window.AddSubview (navigationController.View);
	
	window.MakeKeyAndVisible ();

	return true;
}

正如注释所建议的,这个方法在Application实例化后且已经准备好运行之时,由Objective-C运行时来调用。第一句 (window.AddSubview)被注释掉了,我们会在谈论Model View Controller(MVC)模式的时候来研究它的真正作用。

下一句window.MakeKeyAndVisible,设置MainWindow为主窗口并让其显示出来。在 iPhone开发中,真正有意思的事情是你永远有且有一个窗口在显示。如果想在iPhone应用程序中显示不同的界面,你要创建新的视图,并用视图控制器 把其“推”到前端。然而,你不调用这个方法,iPhone OS就不会发送事件到你的窗口上。MakeKey这个部分是真正起作用的,而AndVisible部分实际上留有传统OS X Cocoa框架的痕迹。

我们来添加一些新代码到这个文件中。在我们创建Outlets的时候,我们是在AppDelegate中创建它们的。那意味着它们会出现在 AppDelegate类中,所以可以在这里来访问它们。和传统的.NET GUI编程有一点不同的是,通常会有一个MainWindow.cs文件,在那里面来处理所有窗口相关的代码。而在这里,我们遵循Objective-C 的模式,就把代码放在AppDelegate中。

我们来把AppDelegate类改为如下这样子:

// The name AppDelegate is referenced in the MainWindow.xib file.

public partial class AppDelegate : UIApplicationDelegate

{
	//---- number of times we've clicked
	protected int _numberOfClicks;

	// This method is invoked when the application has loaded its UI and its ready to run
	public override bool FinishedLaunching (UIApplication app, NSDictionary options)
	{
		// If you have defined a view, add it here:
		// window.AddSubview (navigationController.View);

		window.MakeKeyAndVisible ();
		
		//---- wire up our event handler
		this.btnClickMe.TouchDown += BtnClickMeTouchDown;

		return true;
	}

	protected void BtnClickMeTouchDown (object sender, EventArgs e)
	{
		//---- increment our counter
		this._numberOfClicks++;
		//---- update our label
		this.lblResult.Text = "Hello World, [" + this._numberOfClicks.ToString () + "] times";
	}

	// This method is required in iPhoneOS 3.0
	public override void OnActivated (UIApplication application)
	{
	}
}

第一件事情,我们添加了一个变量来跟踪点击次数, _numberOfClicks。接着,我们添加这行代码:this.btnClickMe.TouchDown += BtnClickMeTouchDown;

这就把btnClickMe的TouchDown事件(类似于OnClick)挂接到处理程序BtnClickMeTouchDown上

接着,在BtnClickMeTouchDown中,我们简单地用按钮被点击多少次的数量值来更新标签的显示内容。

好了,我们已经完成了所有编程,让我们来构建和运行一下。首先来构建。在菜单中,选择Build : Build All。如果目前为止你都正确的按部就班的话,它应该能构建成功。下一步,就是在iPhone模拟器上运行它。在工具栏上,确保 Debug|iPhoneSimulator被选中,如图:

接着,在菜单中选择Run : Run。在MonoTouch的评估版中,你只能在模拟器中运行,如果你打算在iPhone中运行,你会得到一个错误。

如果一切正常,模拟器会显示出来(实际上,它有可能隐藏在MonoDevelop窗口的背后,所以你需要切换过去),那么你就能看到如下所示的效 果:

点击按钮将会产生下图的结果:

恭喜你!你已经创建并跑起你的第一个iPhone应用程序了。

Actions(动作)

在我们刚刚创建的应用程序中,我们有一些Outlets,在代码中可以藉由属性来访问控件。就像在其他.NET GUI模型中,我们能把事件处理程序挂接到它们之上,来对事件作出响应。不过MonoTouch提供了另外一种响应用户输入的方式。这称之为 Actions。Actions类似于WPF的Commands,用这种方式,多个控件可以调用同一个方法,然后依据调用者是谁来决定如何去处理。让我们 来稍微仔细地研究一下。确保你已经在MonoDevelop打开了Example_HelloWorld_1应用程序了。

双击MainWindow.xib文件来在Interface Builder中打开它。现在在标签控件下面添加两个按钮,类似下图:

再次,我们要针对Leopard和Snow Leopard作出不同的说明,你要确定按照正确的部分进行操作。

【SNOW LEOPARD指示开始】

在Library窗口中,确保选中“Classes”标签页,并再次在顶部的下拉列表框中选择“Other Classes”。接着,在上面选择AppDelegate,在下面选择“Actions”标签页。创建一个名为ActionButtonClick的 Action。你的Library窗口应该看起来如下所示:

【SNOW LEOPARD指示结束】

【LEOPARD指示开始】

在窗口管理器中,确保选中App Delegate 。接着在Identity Inspector窗口中,在“Class Actions”里面创建一个名为ActionButtonClick的Action。你的Identity Inspector应该看起来如下所示:

【LEOPARD指示结束】

我们刚刚在App Delegate上创建好了一个名为ActionButtonClick的通用动作。现在,要做的就是把它关联到按钮的 TouchDown事件上,以便在按钮被点击的时候,这个Action能被调用。

首先,选择一个动作按钮,接着转到Connections Inspector,把Touch Down拖动Document窗口中的App Delegate。如下图所示:

注意,在我们拖到App Delegate的时候,会显示出一个可用Actions的列表。选择ActionButtonClick,现在按钮上的TouchDown事件就关联到 这个动作上了:

为两个动作按钮都进行同样的操作。如果我们在Connections Inspector中查看App Delegate,会这样显示:

通过点击“Multiple”旁边的箭头,可展开和ActionButtonClick相关的控件。保存好.xib文件后,回到 MonoDevelop中。

如果我们看一下MainWindow.designer.cs,会发现多了一行新代码:

[MonoTouch.Foundation.Export("ActionButtonClick")] 

partial void ActionButtonClick (MonoTouch.UIKit.UIButton sender);

这是我们的Action的分部声明。注意它用MonoTouch.Foundation.Export特性标记进行了装饰。这使 Objective-C运行时可以找到关联到我们Action上的适当方法。编译器实际上会忽略没有任何实现的分部方法(正如我们在这里所见的这个),那 么这个分部方法的声明实际上是为了在实现它的时候可以获得代码完成的功能。如果我们回到Main.cs,会看到它的真正作用。在AppDelegate类 中,只要键入“partial”就会自动地得到ActionButtonClick的自动完成代码:

我们把如下代码写在里面:

partial void ActionButtonClick (UIButton sender)

{
	//---- show which button was clicked
	this.lblResult.Text = sender.CurrentTitle + " Clicked";
}

现在,如果你运行应用程序,在动作按钮上点击,将会看到如下所示的效果:

此时,我们已经完整地经历了用MonoTouch来开发基本iPhone应用程序的过程。现在,你应该对MonoTouch应用程序的结构、利用事 件处理用户交互,以及用Actions来处理用户交互有了基本的了解。

不过,还有一件重要的事情被忽略了,我们应用程序只具有一个界面。在下一篇文章《The Model-View-Controller Pattern in MonoTouch》中,我们将会谈及具有多个界面的应用程序。

示 例代码

查看英文原文:MonoTouch: .NET Development for the iPhone

[转载]使用jQuery.AutoComplete完成仿淘宝商品搜索功能(改进了键盘上下选择体验)

mikel阅读(1091)

[转载]使用jQuery.AutoComplete完成仿淘宝商品搜索功能(改进了键盘上下选择体验) – kyo-yo – 博客园.

其实这个已经是个比较常见的功能了,网上也有很多人做过这个了,但是很多都是仅仅做了一些基本的网页上自动完成功能,没有与具体的数据库进行联动,我今天所介绍这个自动完成的就是我修改的JQuery.AutoComplete+数据库的一个解决方案

首先来看一些效果图:

pic1

这个是淘宝首页的搜索效果

pic3

京东首页的搜索效果

pic2

我修改的jQuerzy.AutoComplete实现的效果

一、实现效果分析

我要实现的效果就是和GOOGLE类似,需要满足一下3个要求(因为这样我认为是最好的用户体验,毕竟GOOGLE做了那么久了):

1、首先根据关键字列出关键字相关的信息(包含统计信息)

2、可以使用键盘上下键选择(默认不选中第一条),文本框内容根据选择信息变换

3、当选择第一或者最后一条时再向上或向下则取消选中,文本框中内容还原回原先输入的内容(这点比较重要,京东这个就做不好,因为当在向上向下选择的过程中因为文本框内容会跟着换,所以就无法还原到当初用户所输入的内容了)

二、具体实现分析

首先呢因为具体数据时来自于数据库,所以首先在数据库中建立张表用于存放搜索历史记录,每次用户查询的其实就是数据库中的表的记录(也就是上次查询这个关键字的记录数)

1 CREATE TABLE [dbo].[t_KeywordSearchHistory] (
2 [Keyword] [nvarchar] (128) primary key, --关键字
3 [Count] [int] NOT NULL , --搜索次数
4 [RecordCount] [int] NOT NULL --符合关键字的记录数
5 )

上面的表仅仅用于存放用户搜索的关键字,然后在搜索的存储过程或者SQL语句中才进行相应的处理,当用户在页面上输入完关键字然后再点击搜索此时需 要首先根据关键字在数据库中检索相应的数据,若此关键字有相关数据则向t_KeywordSearchHistory表新增一条数据(若此表中已有此关键 字则更新搜索次数和符合关键字的记录数)

01 --上面的是具体的SQL查询代码(统计符合关键字的商品数量
02 if @recordCount>0
03 begin
04 if @keyword <>''
05 begin
06 if exists (select keyword from t_KeywordSearchHistory where keyword=@keyword)
07 begin
08 update t_KeywordSearchHistory set
09 Count=Count+1,
10 RecordCount=@recordCount
11 where keyword=@keyword
12 end
13 else
14 begin
15 insert into t_KeywordSearchHistory values(@keyword,1,@recordCount)
16 end
17 end
18 end
19 else
20 begin
21 update t_KeywordSearchHistory set Count=Count+1,
22 RecordCount=@recordCount
23 where keyword=@keyword
24 end

完成了数据库方面的相关代码后就是界面上的,首先是JQuery.AutoComplete的调用方法:

1 JQuery(function(){
2 jQuery("#txtKeyword").autocomplete("<%=Me.Page.ResolveClientUrl("~/Service.asmx/AutoComplete") %>", {
3 httpMethod: "POST", //使用POST调用WebService
4 dataType: 'xml',//返回数据类型为XML
5 minchar: 1,//最小响应字符数量
6 selectFirst:false,//默认不选中第1条
1 //格式化选项,由于WebService返回的数据是JSON格式,现在要转成HTML以TABLE形式显示
2 formatItem:function(row,i,max){
1 var obj=eval("("+row+")");//将JSON转换成对象
2 var item="<table id='auto"+i+"' style='width:100%;'>
3 <tr>
4 <td align='left'>"+obj.value+"</td>
5 <td align='right' style='color:green;'>"+obj.num+"</td>
6 </tr>
7 </table>";
8 return item;
9 },
1 //格式化结果,当选中时返回具体的值
2 formatResult:function(row,i,max){
3 var obj=eval("("+row+")");
4 return obj.value;
5 }
6 });
7 });

WebService代码:

1 [WebMethod()]
2 public string[] GetGoodsAutoComplete(string q)
3 {
4 List<string> list = new List<string>();
01 //JSON格式模板,同时以换行符分隔,在JS脚本中会进行处理
02 string template = "{{value:'{0}',num:'{1}'}}" + System.Environment.NewLine;//+”\n”
03 SQLCommand cmd = new SqlCommand();
04 SqlDataReader reader = null;
05 cmd.CommandText = "GetAutoComplete";
06 cmd.CommandType = CommandType.StoredProcedure;
07 cmd.Parameters.Add("@keyword", SqlDbType.NVarChar, 128).Value = q;
08 try {
09 reader = Tools.Data.SQLServerHelper.GetReader(VolkHelper.GetDBConnString(), cmd);
10 if (reader != null) {
11 while (reader.Read()) {
12 string s = string.Format(template, (string)reader["keyword"], "约" + (string)reader["num"] + "件商品");
13 list.Add(s);
14 }
15 }
16 }
17 catch (Exception ex) {
18
19 }
20 return list.ToArray();
21 }

接下来就是我修改的jQuery.AutoComplete.js,由于代码太长,我在文章最后已经加了下载的链接所以就不把代码全部贴出来了,仅贴我修改的地方:

1 function moveSelect(step) {
2 listItems.slice(active, active + 1).removeClass(CLASSES.ACTIVE);
3 movePosition(step);
4 var activeItem = listItems.slice(active, active + 1).addClass(CLASSES.ACTIVE);
5 //当动作对象为空时还原用户输入的值
01 if (activeItem[0] != null || activeItem[0] != undefined) {
02 input.value = jQuery(activeItem[0]).find("td:first").text();
03 }
04 if (active >= 0) {
05 if (options.scroll) {
06 var offset = 0;
07 listItems.slice(0, active).each(function() {
08 offset += this.offsetHeight;
09 });
10 if ((offset + activeItem[0].offsetHeight - list.scrollTop()) > list[0].clientHeight) {
11 list.scrollTop(offset + activeItem[0].offsetHeight - list.innerHeight());
12 } else if (offset < list.scrollTop()) {
13 list.scrollTop(offset);
14 }
15 }
16 }
17 };
18
19 function movePosition(step) {
20 if (active < 0 && step == -1) {
21 active = listItems.size()-1;
22 return;
23 }
24 active += step;
1 //光标不再列表时还原用户输入的值
2 if (active < 0) {
3 active = -1;
4 input.value = oldValue;
5 return;
6 }
7 //超出关键字列表时还原用户输入的值
1 if (active >= listItems.size()) {
2 active = -1;
3 input.value = oldValue;
4 return;
5 }
6 }

已经684行开始:

01 next: function() {
02 if (active == -1) {
03 oldValue = input.value;//一开始将用户输入的值存入一个指定的变量
04 }
05 moveSelect(1);
06 },
07 prev: function() {
08 if (active == -1) {
09 oldValue = input.value;
10 }
11 moveSelect(-1);
12 },

以上就完成了自动完成的全部的必须条件了,如果对jQuery.Autocomplete不熟悉的话可以去这里看下具体的使用方法。我在这就不详细说明了。

有网友反映jQuery.AutoComplete无法调试成功,本来在写文章中忘了注明了,就是在webservice中需要添加这个配置节:

01 在system.web配置节下添加:
02 <!--webservice设置-->
03 <webServices>
04 <protocols>
05 <add name="HttpPost"/>
06 <!--<add name="HttpGet"/>
07 <add name="HttpSoap"/>
08 <add name="Documentation"/>-->
09 </protocols>
10 </webServices>

同时在webservice中需要为webservice中添加以下特性:

1 [System.Web.Script.Services.ScriptService()]
2 [WebService(Namespace = http://tempuri.org/)]
3 [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]

其中[System.Web.Script.Services.ScriptService()]特性需要VS2008才拥有,否则是无法调试成功的

附我修改的jQuery.AutoComplete.rar下载:点我下载

PS:大家如果觉得好帮忙点下推荐,谢谢大家了!

[转载]用SMO(sql server management object)生成创建表的脚本

mikel阅读(964)

[转载]用SMO(sql server management object)生成创建表的脚本 – 从挨踢到IT – 博客园.

我本人是做C# winform 开发的。

最近接触一个任务。要根据SQL里一个现有的表生成创建这个表的脚本。

先是想从存储过程的角度解决问题

在网上看了一些资料,发现MSSQL本身没有这个功能,要自己去写。

而其他的数据库对象(视图,存储过程,触发器)则可以通过 SPHelp_Text来解决。

查一些资料无果后,决定自己研究一下。

看了一下SQL的联机文档 ,发现有SMO开发的方式。

如果要生成脚本,需要的引用 为

C:\Program Files (x86)\Microsoft SQL Server\100\SDK\Assemblies\Microsoft.SQLServer.ConnectionInfo.dll

C:\Program Files (x86)\Microsoft SQL Server\100\SDK\Assemblies\Microsoft.SQLServer.Management.Sdk.Sfc.dll

C:\Program Files (x86)\Microsoft SQL Server\100\SDK\Assemblies\Microsoft.SQLServer.Smo.dll

C:\Program Files (x86)\Microsoft SQL Server\100\SDK\Assemblies\Microsoft.SqlServer.SmoExtended.dll

C:\Program Files (x86)\Microsoft SQL Server\100\SDK\Assemblies\Microsoft.SqlServer.SqlEnum.dll

下面做一个抛砖引玉,贴一下生成脚本的源码

代码


using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Common;
using System.Collections.Specialized;

namespace geyunfei
{
class Program
{
static void Main(string[] args)
{

//初始化一个连接
Server server = new Server(new ServerConnection(
localhost, sa, “”));
//得到数据库
var srcDb = server.Databases[TestDB];
//得到表
Table table = srcDb.Tables[Table1];

//初始化Scripter
Scripter a = new Scripter();
a.Options.Add(ScriptOption.DriAllConstraints);
a.Options.Add(ScriptOption.DriAllKeys);
a.Options.Add(ScriptOption.Default);
a.Options.Add(ScriptOption.ContinueScriptingOnError);
a.Options.Add(ScriptOption.ConvertUserDefinedDataTypesToBaseType);
a.Options.Add(ScriptOption.IncludeIfNotExists);

UrnCollection collection = new UrnCollection();

collection.Add(table.Urn);

var sqls = a.Script(collection);

foreach (var s in sqls)
{
System.Console.WriteLine(s);
}

}
}
}

附一些没用的话:

怎么找到使用SMO这个方式的。。。

1.接到任务,第一反应,存储过程。在网上查了一堆资料,发现都是程序员自己写的,MS没有提供类似于Sphelp_text的方法,虽然也可以 用,但是大多针对 特定版本的数据库,不好维护。

2.转而准备使用反应,用SQL TO Linq的文件生成脚本,但是,仍然上个原因,不好维护这个东西。

3.想起来Sqlserver mangement studio里可以生成脚本 。于是自己翻SSMS的动态 连接库,根据 名称试了几个DLL的名称,太复杂 ,没有搞定。

4.于是开始查SQL的联机文档,发现有这个功能,试了一下,还真好用,嘿嘿。