[Google]调试学习Google AJAX APs好去处

mikel阅读(824)

转载;http://www.xuewolf.com/?p=104
Google AJAX APIs Playground

Google AJAX APIs Playground

 

 

 

 

 

 

 

 

 

给调试和学习google api的朋友(绝大多数应该是地图类api吧!)一个调试和学习google api的好去处 — — Google AJAX APIs Playground.

本周一,Google发布了他的第二个版本。(看来老外清明节没有放三天假!)Google依然在跟我们搞笑,该工具在google自家的浏览器上无法正常使用。

这个版本加入了几个新特性:

1.支持断点。

2.用Firebug Lite做调试工具。

3.代码编辑框显示行号了。

4.可以直接编辑示例的HTML了。

[JQuery]JGTranslation:基于GOOGLE AJAX API的jQuery

mikel阅读(784)

转载:http://www.evlook.com/?p=126

平常上网遇见不懂单词和句子的时候,都喜欢用翻译软件来翻译一下,一般都用有道和google。这几天看google API的时候发现他好像早就提供了翻译的方法,不过好像没什么人用 :( 那我来用,呵呵。

写了个JQuery的小插件,结合google ajax API,提供页面文字的即时翻译功能,只要你指定要使用即时翻译的模块ID并指定翻译语言(如果不指定就按照操作系统默认语言进行翻译。)就能简单调用,非常方便。

如果你的blog是中文但是很多国外访问者那你可以用了试试,如果你的是英文blog,但是很多用中文的用户访问,你也可以使用。总之都是为了大家提供便利,呵呵。

可以选择下面的两段文字看看效果

曲曲折折的荷塘上面,弥望的是田田的叶子。叶子出水很高,像亭亭的舞女的裙。层层的叶子中间,零星地点缀着些白花,有袅娜地开着的,有羞涩地打着朵儿的; 正如一粒粒的明珠,又如碧天里的星星,又如刚出浴的美人。微风过处,送来缕缕清香,仿佛远处高楼上渺茫的歌声似的。这时候叶子与花也有一丝的颤动,像闪电 一般,霎时传过荷塘的那边去了。叶子本是肩并肩密密地挨着,这便宛然有了一道凝碧的波痕。叶子底下是脉脉的流水,遮住了,不能见一些颜色;而叶子却更见风 致了
Now that I’ve lost everything to you,
you say you want to start something new,
and it’s breaking my heart you’re leaving,
baby I’m grieving.
But if you wanna leave take good care,
hope you have a lot of nice things to wear,
but then a lot of nice things turn bad out there.

一、你必须引用google提供的API

<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("language", "1");
</script>

二、翻译控件用到的默认样式

.JGTranslationPopStyle{font : normal normal normal 12px Verdana, Arial, Helvetica, sans-serif;border:2px solid #C5D7EF;background:#fff;}
.JGTranslationPopStyle p{padding:3px;margin:0px;line-height:150%;}
.JGTranslationPopStyle div{text-align:right;background:#E5ECF9;}

三、调用方法

$(selector).JGTranslation(options)
//可选参数
//Language:string(default = "userLanguage")
//PopStyle: string(default = "JGTranslationPopStyle")
//Branding:boolean(default = true)

示例:

<div id="TS1">
曲曲折折的荷塘上面,弥望的是田田的叶子。叶子出水很高,像亭亭的舞女的裙。层层的叶子中间,零星地点缀着些白花,有袅娜地开着的,有羞涩地打着朵儿的;正如一粒粒的明珠,又如碧天里的星星,又如刚出浴的美人。微风过处,送来缕缕清香,仿佛远处高楼上渺茫的歌声似的。这时候叶子与花也有一丝的颤动,像闪电一般,霎时传过荷塘的那边去了。叶子本是肩并肩密密地挨着,这便宛然有了一道凝碧的波痕。叶子底下是脉脉的流水,遮住了,不能见一些颜色;而叶子却更见风致了
</div>
<div id="TS2">
Now that I've lost everything to you,
you say you want to start something new,
and it's breaking my heart you're leaving,
baby I'm grieving.
But if you wanna leave take good care,
hope you have a lot of nice things to wear,
but then a lot of nice things turn bad out there.
</div>
$('#TS1').JGTranslation({Language:'en'})
$('#TS2').JGTranslation()


点击下载jquery.JGTranslation.js

[开发技巧]VS2008快捷键大全

mikel阅读(695)

Ctrl+m+Crtr+o折叠所有大纲
Ctrl+M+Crtr+P: 停止大纲显示
Ctrl+K+Crtr+C: 注释选定内容
Ctrl+K+Crtr+U: 取消选定注释内容
Ctrl+J : 列出成员 智能感知
Shift+Alt+Enter: 切换全屏编辑
Ctrl+B,T / Ctrl+K,K: 切换书签开关
Ctrl+B,N / Ctrl+K,N: 移动到下一书签
Ctrl+B,P: 移动到上一书签
Ctrl+B,C: 清除全部标签
Ctrl+I: 渐进式搜索
Ctrl+Shift+I: 反向渐进式搜索
Ctrl+F: 查找
Ctrl+Shift+F: 在文件中查找
F3: 查找下一个
Shift+F3: 查找上一个
Ctrl+H: 替换
Ctrl+Shift+H: 在文件中替换
Alt+F12: 查找符号(列出所有查找结果)
Ctrl+Shift+V: 剪贴板循环
Ctrl+左右箭头键: 一次可以移动一个单词
Ctrl+上下箭头键: 滚动代码屏幕,但不移动光标位置。
Ctrl+Shift+L: 删除当前行
Ctrl+M,M: 隐藏或展开当前嵌套的折叠状态
Ctrl+M,L: 将所有过程设置为相同的隐藏或展开状态
Ctrl+E,S: 查看空白
Ctrl+E,W: 自动换行
Ctrl+G: 转到指定行
Shift+Alt+箭头键: 选择矩形文本
Alt+鼠标左按钮: 选择矩形文本
Ctrl+Shift+U: 全部变为大写
Ctrl+U: 全部变为小写
代码快捷键
Ctrl+Shift+空格键 / Ctrl+K,P: 参数信息
Ctrl+K,I: 快速信息
Ctrl+E,U / Ctrl+K,U: 取消选定注释内容
Ctrl+K,M: 生成方法存根
Ctrl+K,X: 插入代码段
Ctrl+K,S: 插入外侧代码
F12: 转到所调用过程或变量的定义
窗口快捷键
Ctrl+W,W: 浏览器窗口
Ctrl+W,S: 解决方案管理器
Ctrl+W,C: 类视图
Ctrl+W,E: 错误列表
Ctrl+W,O: 输出视图
trl+W,P: 属性窗口
Ctrl+W,T: 任务列表
Ctrl+W,X: 工具箱
Ctrl+W,B: 书签窗口
Ctrl+W,U: 文档大纲
Ctrl+D,B: 断点窗口
Ctrl+D,I: 即时窗口
Ctrl+Tab: 活动窗体切换
Ctrl+Shift+N: 新建项目
Ctrl+Shift+O: 打开项目
Ctrl+Shift+S: 全部保存
Shift+Alt+C: 新建类
Ctrl+Shift+A: 新建项
Shift+Alt+Enter: 切换全屏编辑
Ctrl+B,T / Ctrl+K,K: 切换书签开关
Ctrl+B,N / Ctrl+K,N: 移动到下一书签
Ctrl+B,P: 移动到上一书签
Ctrl+B,C: 清除全部标签
Ctrl+I: 渐进式搜索
Ctrl+Shift+I: 反向渐进式搜索
Ctrl+F: 查找
Ctrl+Shift+F: 在文件中查找
F3: 查找下一个
Shift+F3: 查找上一个
Ctrl+H: 替换
Ctrl+Shift+H: 在文件中替换
Alt+F12: 查找符号(列出所有查找结果)
Ctrl+Shift+V: 剪贴板循环
Ctrl+左右箭头键: 一次可以移动一个单词
Ctrl+上下箭头键: 滚动代码屏幕,但不移动光标位置。
Ctrl+Shift+L: 删除当前行
Ctrl+M,M: 隐藏或展开当前嵌套的折叠状态
Ctrl+M,L: 将所有过程设置为相同的隐藏或展开状态
Ctrl+M,P: 停止大纲显示
Ctrl+E,S: 查看空白
Ctrl+E,W: 自动换行
Ctrl+G: 转到指定行
Shift+Alt+箭头键: 选择矩形文本
Alt+鼠标左按钮: 选择矩形文本
Ctrl+Shift+U: 全部变为大写
Ctrl+U: 全部变为小写 

[FMS]FMS3系列(六):使用远程共享对象(SharedObject)实现多人时时在线聊天(Fl

mikel阅读(894)

转载:http://www.cnblogs.com/beniao/archive/2009/05/04/1447774.html
FMS开发中,经常会使用共享对象来同步用户和存储数据。对于实现广播文字信息实现聊天的支持非常强大,还可以跟踪用户的时时动作,在开发Flash多人在线游戏中的应用也非常广阔。

      在使用FMS开发共享对象时需要注意,只有使用Flash Media Interactive Server或Flash Media Development Server这两个版本时才能够创建和使用远程共享对象,来实现多客户端的应用程序之间共享数据。如果是使用的Flash Media Streaming Server版FMS是不能创建远程共享对象的,只能创建本地共享对象,类似于传统Web开发中的Cookie。

      使用共享对象(SharedObject)来开发时时文字聊天其实是很简单的,SharedObject可以跟踪和广播消息,连接到 SharedObject中的其中任何一个客户端改变了SharedObject中的数据,SharedObject就会将最新的数据广播到连接到它的所 有客户端。从某种角度可以理解为远程的SharedObject是一个同步很多用户的一个网络中心。下图为官方发布的SharedObject广播消息 图:

                  

      

      本文是通过实现一个简单的文字聊天来介绍FMS中的远程共享对象的使用,首先在FMS中建立好应用程序名,既在FMS的安装目录下的applications下建立一文件夹,来作为共享对象应用程序使用,如下图所示:

                  

      如上图,SharedObjectApp就是为实现聊天建立的一个FMS应用文件夹,其下的 sharedobjects/_definse_为成功创建远程对象后自动生成的目录。如果你所创建的为永久性的远程共享对象,则在该目录下还将会有一个 以.fso为扩展名的远程共享对象文件。

      要创建远程共享对象,首先需要连接到FMS应用,然后通过SharedObject.getRemote()方法来完成远程共享对象的创建,通过给远程共享对象添加同步事件监听,远程共享对象里的数据一但发生改变就会自动触发该事件,来实现同步数据。

private function onClick():void
{
    nc 
= new NetConnection();
    nc.connect(
"rtmp://192.168.1.101/SharedObjectApp");
    nc.addEventListener(NetStatusEvent.NET_STATUS,onNetStatusHandler);
}
private function onNetStatusHandler(evt:NetStatusEvent):void
{
    
this.panChat.title+="("+evt.info.code+")";
    
if(evt.info.code=="NetConnection.Connect.Success")
    {
        
//创建一个远程共享对象
        
//参数:远程共享对象的名称 | 连接到的应用程序的URI | 远程共享对象是否为永久远程对象
        so = SharedObject.getRemote("RemotingSO",nc.uri,true); //将生成SO.fso
        
//远程对象(SharedObject)同步事件的监听
        so.addEventListener(SyncEvent.SYNC,onSyncHandler);
        
//远程共享对象连接到服务器
        so.connect(nc);
    }
}

 

      上面代码块实现了连接到FMS应用,成功连接后便创建远程共享对象(RemotingSO),同时还为远程共享对象添加了同步事件监听,通过onSyncHandler方法来处理事件。

      在继续实现聊天功能前,我们需要编写一个通用方法,该方法提供将一个数组里的数据转移到另一个数组,如下代码块:

private function convertArrayCollection(arrNew:ArrayCollection,arrOld:ArrayCollection):void
{
     arrNew.removeAll();
  
     
for(var i:int=0;i<arrOld.length ;i++)
     {
          arrNew.addItemAt(arrOld.getItemAt(i),i);
     }
}

 

      下面我们通过发送消息的流程开始,首先是发送消息,通过自定义Message类来封装消息内容:

 1 package flex.VO
 2 {
 3     public class Message
 4     {
 5         public var NickName:String;  //用户呢称
 6         public var Context:String;    //消息内容
 7         
 8         public function Message()
 9         {
10         }
11     }
12 }

 

      在发送消息的时候,通过此Message类来封装发送消息的数据,然后将其发布到FMS中的远程共享对象,更新远程共享对象中的数据。

private function onSend():void
{
    var tempCollection:ArrayCollection 
= new ArrayCollection();
    
if(so.data.msgCollection != null)
    {
        convertArrayCollection(tempCollection,so.data.msgCollection 
as ArrayCollection);
    }
    
    var msg:Message 
= new Message();
    msg.NickName 
= this.txtUser.text;
    msg.Context 
= this.txtMessage.text;
    tempCollection.addItem(msg);
    //更新远程共享对象中的属性值
    so.setProperty(
"msgCollection",tempCollection);
    
    
this.txtMessage.text="";
}

 

      实现了发送消息(将消息添加到远程共享对象并更新远程共享对象的属性值),如果有多个客户端连接到该远程共享对象,这时就回触发远程共享对象的同步事件,通过同步事件处理方法就可以将远程共享对象中的数据同步到客户端。如下代码块:

private function onSyncHandler(evt:SyncEvent):void
{
    
if(so.data.msgCollection!=null)
    {
        var tempCollection:ArrayCollection 
= new ArrayCollection();
        convertArrayCollection(tempCollection,so.data.msgCollection 
as ArrayCollection);
        
        
this.msgText.text="";
        
for(var index:int=0;index<tempCollection.length;index++)
        {
            var message:Object 
= tempCollection.getItemAt(index);
            var displayMessage:String 
= message.NickName+"说:"+message.Context;
            
this.msgText.text += displayMessage + "\n";
        }
    }
}

 

      如上便完成了整个文字聊天的功能开发,主要应用到的技术点就是通过远程共享对象来同步用户数据。下面为完整的Flex端代码:

完整的Flex端代码

 

      程序运行截图如下:

            

                                                  图1—-FMS状态图

            

                                                图2—-聊天客户端(张三)

                  

                                          图3—-聊天客户端(李四)

            

 

      如上图,在FMS应用目录下创建了一后缀为.fso的文件,这就是永久性的远程共享对象文件名。在使用远程共享的时候,根据实际需求来 确定是否使用永久性的远程共享对象,一般做聊天应用我个人建议使用临时远程共享对象(不生成.fso文件),要存储聊天记录可以通过其他方式来保存。

      详细大家可以查看官方提供的文档,在FMS的安装目录下就有,我的是D:\Adobe\Flash Media Server 3\documentation\flashmediaserver_AS3LR\index.html

 

      本文就介绍于此,如文中有什么问题,请大家拍砖指正。本文示例源代码下载

 

版权说明

  本文属原创文章,欢迎转载,其版权归作者和博客园共有。  

  作      者:Beniao

 文章出处:http://beniao.cnblogs.com/  或  http://www.cnblogs.com/

       

[JQuery]jquery.load()使iframe随内容改变而自适应高度

mikel阅读(964)

很高兴,终于使用JQuery实现了点击外部链接,更改iframe内容时,iframe的高度自适应问题。
失败的测试就不说了,来直接的。
两个链接和iframe:

Java代码
  1. <li><a href="selfinfo.jsp" target="c-c-iframe" title="个人信息" >个人信息</a></li>  
  2. <li><a href="modifypass.jsp" target="c-c-iframe" title="修改密码" >修改密码</a></li>  
  3.   
  4. <iframe src="init.jsp" id="c-c-iframe" name="c-c-iframe" width="500px;"  frameborder="0" scrolling="no" marginwidth="0" marginheight="0"></iframe>  

js代码:

Java代码
  1. <script type="text/JavaScript">  
  2. <!–  
  3. $(function(){  
  4.     $("#c-c-iframe").load(function(){         
  5.         $(this).height($(this).contents().find("#content").height() + 40);  
  6.     });  
  7.       
  8. });  
  9. –>  
  10. </script>  

这里的find("#content")是找出iframe内容文档中的id为content的高度(另外比如find("body")),并设置给iframe,
类似的还可以设置宽度,留给需要的朋友尝试吧。
这样就解决了iframe不会因为内容过大被挡住的问题(因为我设置了scrolling="no")。
PS:基本上我会优先考虑使用iframe来实现无刷新,兼容浏览器的后退按钮;而且使用iframe加载flash是很爽的,不用写什么js调用,object标签,还符合W3C标准。
2008年11月28日17:13:31 ,今天使用过程中根据实际情况进行了一下改良,代码如下:

Java代码
  1.     <script type="text/JavaScript">  
  2. <!–  
  3. $(function(){  
  4.     $("#workArea").load(function(){       
  5.         var height = $(this).contents().find("#box").height() + 40;  
  6. //这样给以一个最小高度  
  7.         $(this).height( height < 400 ? 400 : height );  
  8.     });  
  9.       
  10. });  
  11. –>  
  12. </script>  

另发现使用find("body")不太好使,高度不准确。

[SVN]项目管理实践教程二、源代码控制【Source Control Using VisualSV

mikel阅读(696)

在第一篇文章 项目管理实践教程一、工欲善其事,必先利其器【Basic Tools】发布后,根据大家的回复,我需要向大家说明几个问题:

1.为什么要用VisualSVN Server,而不用Subversion?

回答:

因为如果直接使用Subversion,那么在Windows 系统上,要想让它随系统启动,就要封装SVN Server为windws service,还要通过修改配置文件来控制用户权限,另外如果要想以Web方式【http协议】访问,一般还要安装配置Apache,如果是新手,岂不 是很头痛?而VisualSVN Serve集成了Subversion和Apache,省去了以上所有的麻烦。安装的时候SVN Server已经封装为windws service,Apache服务器的配置也只是在图像界面上,指定认证方式、访问端口等简单操作;另外,用户权限的管理也是通过图像界面来配置。

2.为什么不用TFS?

回答:

因为我们一开始就是用Subversion和TortioseSVN,所以就没有更换其他的软件。至于TFS至今没有用过,其实,我只是看了一些的文章而已,对它也不了解。

3.VisualSVN Server是免费的吗?

回答:

是的,VisualSVN Server是免费的,而VisualSVN是收费的。VisualSVN是SVN的客户端,和Visual Studio集成在一起, VisualSvn Server是SVN的服务器端,包括Subversion、Apache和用户及权限管理,优点在上面已经说过了。

 

好了,言归正传,正式开始我们今天的教程。

 

一、VisualSVN Server的配置和使用方法【服务器端】

安装好VisualSVN Server后【安装过程看这里】,运行VisualSVN Server Manger,下面是启动界面:

 

好的,下面我来添加一个代码库【Repository】,如下图:

按上图所示,创建新的代码库,在下图所示的文本框中输入代码库名称:

 

注意:上图中的CheckBox如果选中,则在代码库StartKit下面会创建trunk、branches、tags三个子目录;不选中,则只创建空的代码库StartKit。

点击OK按钮,代码库就创建成功了。

创建完代码库后,没有任何内容在里面。我会在这个教程的第二部分说明如何迁入源代码。

下面,我们开始安全性设置,在左侧的Users上点击右键:

 

输入上面的信息,点击OK,我们就创建一个用户了。按照上面的过程,分别添加用户Developer1、tester1、manager1,好了,我们开始添加这些用户到我们刚才创建的项目里:

点击上图中的"Add…"按钮,在下图中选择我们刚才添加的用户,点击OK按钮:

说明:大家可能注意到了下图中的Groups,是的,你也可以先创建组,把用户添加到各个组中,然后对组进行授权,操作比较简单,在此略过。

按照下图所示,分别对用户【或组】进行授权:

点击"确定"按钮,上面的用户就具有了访问StartKit代码库的不同权限。

因为用户starter在团队中是新来者,不希望他向代码库中提交新代码,所以他只能读取代 码库中的代码,不能提交代码。tester1是测试人员,不负责代码编写,所以也是只读权限。而Developer1和manager1是开发人员和项目 经理,自然具有读、写的权限。

在实际的项目开发过程中,Developer和tester往往不可能只有一个人,这时候使用组来授权更加方便,这个大家可以自己练习一下。

二、TotoiseSVN的基本使用方法

 

项目管理实践教程一、工欲善其事,必先利其器【Basic Tools】中,我已经讲解了怎样安装TortoiseSVN。在上面的讲解中已经讲了怎么使用VisualSVN Server了,今天我要讲的是,TortoiseSVN的简单使用方法。

一、签入源代码到SVN服务器

假如我们使用Visual Studio在文件夹StartKit中创建了一个项目,我们要把这个项目的源代码签入到SVN Server上的代码库中里,首先右键点击StartKit文件夹,这时候的右键菜单如下图所示:

图2-2-1

点击Import,弹出下面的窗体,其中http://zt.net.henu.edu.cn 是服务器名,svn是代码仓库的根目录,StartKit是我们在上个教程中添加的一个代码库:

说明:左下角的CheckBox,在第一次签入源代码时没有用,但是,在以后你提交代码的时候是非常有用的。

图2-2-2

点击OK按钮,会弹出下面的窗体,要求输入凭据:

图2-2-3

在上面的窗体中输入用户名和密码,点击OK按钮:

图2-2-4

如上图所示,好了,源代码已经成功签入SVN服务器了。这时候团队成员就可以迁出SVN服务器上的源代码到自己的机器了。

二、签出源代码到本机

在本机创建文件夹StartKit,右键点击Checkout,弹出如下图的窗体:

图2-2-5

在上图中URL of Repository:下的文本框中输入svn server中的代码库的地址,其他默认,点击OK按钮,就开始签出源代码了。

说明:上图中的Checkout Depth,有4个选项,分别是迁出全部、只签出下一级子目录和文件、只签出文件、只签出空项目,默认的是第一项。上面的例子中,我们也可以使用web的方式访问代码库,在浏览器中输入http://zt.net.henu.edu.cn/svn/StartKit/

这时候也会弹出对话框,要求输入用户名和密码,通过验证后即可浏览代码库中的内容。

 

搞定!源代码已经成功签出到刚才新建的StartKit目录中。

打开StartKit目录,可以看到如下图的文件夹结构:

图2-2-5

一旦你对文件或文件夹做了任何修改,那么文件或文件夹的显示图片机会发生变化。下图中我修改了其中的二个文件:

图2-2-7

大家看一下不同状态所对应的图片:

图2-2-8

我们已经知道怎么将源代码签入到SVN服务器,怎么从服务器签出代码到本机,也简单了解了不同状态所对应的图案啦。

三、提交修改过的文件到SVN服务器

上面的图2-2-7中,我修改了位于Model文件中的二个文件ImageInfo.cs和NewsInfo.cs,下面演示如何提交到SVN服务器。

注意:提交源代码到服务器时,一定确保本机的代码是最新版本,否则可能提交失败,或者造成版本冲突。

在Model文件夹上点击右键或在Model文件下的空白处点击右键,点击SVN Commit…弹出下面的窗体:

图2-2-9

点击OK按钮后,弹出如下图的窗体:

图2-2-10

四、添加新文件到SVN服务器

我们在Model文件下添加一个新的类文件UserInfo.cs,在Model文件下的空白处点击右键,点击SVN Commit…,和上面讲的提交修改过的文件到SVN服务器一样,就可以了。

另外也可以在文件UserInfo.cs上点击右键,点击TortoiseSVN=>>Add,弹出如下图的窗体:

图2-2-11

选中UserInfo.cs文件,点击OK按钮,这样并没有将这个文件提交到SVN服务器,只是将这个文件标记为源代码库库中的文件,并将其状态置为修改状态。之后,我们要再SVN Commit这个文件一次,才可以将其真正提交到SVN服务器上的代码库中。

 

上面讲是添加文件,实际上,添加文件夹的步骤也是一样的,这里就不说了。

 

五、更新本机代码与SVN服务器上最新的版本一致

这个也很简单,只要在需要更新的文件夹上点击右键或在该文件下的空白处点击右键,点击SVN Update,就可以了。

注意:更新操作可能会因为版本冲突而失败,这是可以使用合并【Merge】或其他方法解决;也可能因为锁定【Get Lock】而失败,这是需要先解锁【Release Lock】。

六、重命名文件或文件夹,并将修改提交到SVN服务器

只要在需要重命名的文件或文件夹上点击右键,点击TortiseSVN=>& gt;Rename…,在弹出的窗体中输入新名称,点击OK按钮,就可以了。此方法也不是直接重命名,而是将该文件或文件夹的名称标记为重命名后名称,也 需要我们使用SVN Commit提交到SVN服务器后才真正重命名。

七、删除文件或文件夹,并将修改提交到SVN服务器

最简单就是,你直接删除文件或文件夹,然后使用SVN Commit提交更新到SVN服务器。另外一种方法是在你要删除的文件或文件夹上点击右键=>>TortoiseSVN=>> Delete删除,此方法也不是直接删除,而是将该文件或文件夹的状态置为删除,也需要我们使用SVN Commit提交到SVN服务器后才真正删除。

说明:实际上,从你把源代码迁签入SVN服务器开始,每一个版本的数据和文件,就算是你已经删除了的,也都可以随时迁出。

以上只是TortoiseSVN最简单的几个功能,其实他的功能远不止这些,其他的功能大家可以在使用的过程中慢慢体会,有些功能我会在下面的教程中使用到,到时候会和大家讲清楚用法。

 注意:向SVN服务器提交源代码的时候,一定不要提交bin、obj等文件夹,否则会很麻烦。但是web项目的bin目录除外,但是web项目的bin目录中的引用其他项目而生成的dll不需要提交。

一个好习惯:如果项目中引用了其他的第三方的程序集,比如 EnterpriseLibrary、FCKEditor等,这时候不要简单从他们的安装位置引用,而是在你的解决方案下,添加一个Library的目 录,把需要的程序集复制到这里,然后从Library目录引用,这样有什么好处,自己想一想吧!

如果大家有什么问题,尽管跟帖提问,我一定及时回答。

好了,今天就先写到这里吧,本来说这部分准备写一篇Blog,可是现在写了这么长,还只是说了一点很基本的东西而已,呵呵……

如果你对我讲解的这些内容不熟悉,建议你从头开始看这个系列的教程:项目管理实践系列教程

作者:ttzhangTechnology Life–张涛的技术博客
出处:http://ttzhang.cnblogs.com/
文章版权归博客园和本人共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

[SQL]SqlServer:CTE函数处理递归(WITH语法)

mikel阅读(1487)

     我们在做分类处理的时候,总会遇到递归的处理,比如说地区就是一个例子,中国–北京–西城区,我们可以把这样的信息存储在一个数据表中,用 ParentID区分根节点和叶子节点。假如我们要做导航,得到了”西城区”,但是还要得到他的父级,或夫父级,一种方式是用程序来处理,也是很简单,另 一种方式就是用数据库的功能。既然数据库能完成这件事,何必在用程序呢?

     在SQLServer2005以前的版本中,也能处理这种情况,不过当时用的是存储过程,代码也比较多,表设计的时候,还的加一个表示“深度”的字段,当时我也写过相关的文章,参见:

存储过程实现无限级分类(1)

存储过程实现无限级分类(2)

存储过程实现无限级分类(3)

    但是,在学习SQLServer2005新加的特性的时候,注意到WITH语句能实现这样的功能,并且代码简单,简练,最重要的是好理解。

下面是一张递归的表结构图:

Recursive_1

里边的parentID记录的就是他们之间的关系;

比如我们要查询id = 10008,并且parentID 为10008的数据怎么办呢?如:

Recursive_3

呵呵,不留悬念了,直接上代码吧!其实挺容易理解的:

WITH CategoryInfo AS(
Select id,text,parentid FROM Recursive Where id = 10008
UNION ALL
Select a.id,a.text,a.parentid FROM Recursive AS a,CategoryInfo AS b Where a.parentid = b.id
)
Select * FROM CategoryInfo

 

看看是不是简单,简练,好理解!

赶快试试吧!

这是从上向下查,如果从下向上查,怎么查呢,自己举一反三吧!

存储过程实现无限级分类(1)

    在做考题的的时候,涉及到分类,虽然不是无限级的,但是,为了以后扩展用,想做成无限级,在网上找找了,一个用存储过程作的,虽然添加,编辑,移动,用的 是存储过程,可是在读出来的时候只用了一条Select 语句,感觉挺爽的,下面我把存储过程列出来,我只用到了添加,编辑,没有用到移动。

1,表结构

===================================================
表结构:
表名:Tb_Column
表结构(所有字段非空):
Column_ID     
int 主键(注:非标识)
Column_Name   nvarchar(
50)分类名称
Parent_ID     
int 父分类ID(默认值0)
Column_Path   nvarchar(
1000) 分类路径
Column_Depth  int分类深度(默认值0)
Column_Order  int排序(默认值0)
Column_Intro  nvarchar(
1000)分类说明
================================================

2.添加的存储过程

Create PROCEDURE sp_Column_Insert
(
@Parent_ID 
int,
@Column_Name nvarchar(
50),
@Column_Intro nvarchar(
1000)
)
AS
Declare @Err As 
int
Set @Err
=0
Begin Tran
通过现有记录获取栏目ID
Declare @Column_ID As 
int
Declare @Column_Depth As 
int
Select @Column_ID 
= Max(Column_ID) From Tb_Column
IF @Column_ID Is Not Null
Set @Column_ID 
= @Column_ID+1
Else
Set @Column_ID 
= 1
判断是否是顶级栏目,设置其Column_Path和Column_Order
Declare @Column_Path As nvarchar(
1000)
Declare @Column_Order As 
int
IF @Parent_ID 
= 0
Begin
Set @Column_Path 
=Ltrim(Str(@Column_ID))
Select @Column_Order 
= Max(Column_Order) From Tb_Column
IF @Column_Order Is Not Null
Set @Column_Order 
= @Column_Order + 1
Else 
如果没有查询到记录,说明这是第一条记录
Set @Column_Order 
= 1
深度
Set @Column_Depth 
= 1
End
Else
Begin
获取父节点的路径和深度
Select @Column_Path 
= Column_Path ,@Column_Depth = Column_Depth From Tb_Column Where 
Column_ID
=@Parent_ID
IF @Column_Path Is Null
Begin
Set @Err 
= 1
Goto theEnd
End
获取同父节点下的最大序号
Select @Column_Order 
= Max(Column_Order) From Tb_PicColumn Where Column_Path like 
''+@Column_Path+'|%'  Or Column_ID = @Parent_ID
IF @Column_Order Is Not Null 
如果序号存在,那么将该序号后的所有序号都加1
Begin 
更新当前要插入节点后所有节点的序号
Update Tb_Column Set Column_Order 
= Column_Order +1 Where Column_Order 
>@Column_Order
同父节点下的最大序号加上1,构成自己的序号
Set @Column_Order 
= @Column_Order + 1
End 
Else
Begin
Set @Err
=1
Goto theEnd
End
父节点的路径加上自己的ID号,构成自己的路径
Set @Column_Path 
= @Column_Path + '|' + Ltrim(Str(@Column_ID))
深度
Set @Column_Depth 
= @Column_Depth+1
End
Insert Into Tb_Column(Column_Name,Parent_ID,Column_Path,Column_Depth,Column_Order,Column_Intro) 
Values(@Column_Name,@Parent_ID,@Column_Path,@Column_Depth,@Column_Order,@Column_Intro)
IF @@Error
<>0 
Begin
Set @Err
=1
Goto theEnd
End
更新当前记录之后的记录的ORDER
Update Tb_Column Set Column_Order = Column_Order+1 Where Column_Order  > @Column_Order 
theEnd:
IF @Err
=0
Begin
Commit Tran
Return @Column_ID
End
Else
Begin
    Rollback Tran
Return 
0
End
GO

存储过程实现无限级分类(2)
di。删除的存储过程

Create PROCEDURE sp_Column_Delete
(
@Column_ID 
int
)
AS
Declare @Err As 
int
Set @Err 
= 0
Begin Tran
首先查询该节点下是否有子节点
Select Column_ID From Tb_Column Where Parent_ID 
= @Column_ID
IF @@RowCount
<>0
    Begin
    Set @Err 
= 1
    Goto theEnd
    End
获取该节点的Column_Order,为了删除后整理其他记录的顺序
Declare @Column_Order As 
int
Select @Column_Order 
= Column_Order From Tb_Column Where Column_ID = @Column_ID
IF @Column_Order Is NUll
    Begin
      Set @Err 
=2
      Goto theEnd
    End 
更新其他记录的Column_Order
Update Tb_Column Set Column_Order 
= Column_Order 1 Where Column_Order >@Column_Order 
IF @@Error
<>0
    Begin
      Set @Err 
=3
      Goto theEnd
    End 
删除操作
Delete From Tb_Column Where Column_ID
=@Column_ID
IF @@Error
<>0
    Begin
      Set @Err 
=4
      Goto theEnd
  End 
更新其他记录的Column_ID
Update Tb_Column Set Column_ID= Column_ID  1 Where Column_ID >@Column_ID 
IF @@Error<>0
    Begin
      Set @Err =5
      Goto theEnd
    End 
theEnd:
IF @Err 
= 0 
    Begin
      Commit Tran
      Return 
0 删除成功
    End
Else
    Begin
      IF @Err
=1
  Begin
      Rollback Tran
      Return 
1 有子节点
End
      Else
Begin
      Rollback Tran
      Return 
2未知错误
End
    End
GO

4.编辑的存储过程(没有用到,我自己写了一个简单的只是编辑名称,没有涉及到移动)

Create PROCEDURE sp_Column_Update
(
@Column_ID 
int
,
@Parent_ID 
int
,
@Column_Name nvarchar(
50
),
@Column_Intro nvarchar(
1000
)
)
AS
Declare @Err As 
int

Set @Err
=0
Begin Tran
获取修改前的:Parent_ID,Column_Depth,Column_Order
Declare @oParent_ID As 
int

Declare @oColumn_Depth As 
int
Declare @oColumn_Order As 
int
Declare @oColumn_Path As nvarchar(
1000)
Select @oParent_ID 
= Parent_ID, @oColumn_Depth = Column_Depth,@oColumn_Order = Column_Order, @oColumn_Path = Column_Path  From Tb_Column Where Column_ID =
 @Column_ID
IF @oParent_ID Is Null
    Begin
    Set @Err 
= 1

    Goto theEnd
    End
如果父ID没有改变,则直接修改栏目名和栏目简介
IF @oParent_ID 
=
 @Parent_ID
    Begin
    Update Tb_Column Set Column_Name 
= @Column_Name,Column_Intro = @Column_Intro Where Column_ID =
 @Column_ID
    IF @@Error 
<> 0

    Set @Err 
= 2
    Goto theEnd
    End
Declare @nColumn_Path As nvarchar(
1000)
Declare @nColumn_Depth As 
int

Declare @nColumn_Order As 
int
获取当前节点作为父节点所包含的节点数[包括自身] 注:如果返回 “1” 说明是单节点
Declare @theCount As 
int

Select @theCount 
= Count(Column_ID) From Tb_Column Where Column_ID=@Column_ID Or Column_Path like ''+@oColumn_Path+'|%'
IF @theCount Is Null
Begin
    Set @Err 
= 3
    Goto theEnd
End 
IF @Parent_ID
=0 如果是设置为顶级节点,将节点设置为最后一个顶级节点
Begin
Print '设置为顶级栏目'

Set @nColumn_Path 
= Ltrim(Str(@Column_ID))
Set @nColumn_Depth 
=1

Select @nColumn_Order 
= Max(Column_Order) From Tb_Column
IF @nColumn_Order Is NULL
                  Begin
     Set @Err 
= 4

     Goto theEnd
     End 
Set @nColumn_Order 
= @nColumn_Order  @theCount + 1
更新三部分 1 节点本身 2 所有子节点 2 本树更改之前的后面记录的顺序
Print '更新本栏目之前位置后面的所有栏目[不包括本栏目下的子栏目]的:Column_Order'

Update Tb_Column Set Column_Order 
= Column_Order@theCount Where (Column_Order >@oColumn_Order) And (Column_Path Not like ''+@oColumn_Path+'|%')
IF @@Error 
<> 0

    Begin
    Set @Err 
= 7
    Goto theEnd
    End
Print '更新本栏目的:Parent_ID,Column_Path,Column_Depth,Column_Order,Column_Name,Column_Intro'
Print 
'Order : '+Ltrim(Str(@nColumn_Order))
Update Tb_Column Set Parent_ID
=@Parent_ID,Column_Path = @nColumn_Path,Column_Depth = @nColumn_Depth,Column_Order = @nColumn_Order, Column_Name = @Column_Name,Column_Intro = @Column_Intro Where Column_ID =
 @Column_ID
IF @@Error 
<> 0

    Begin
    Set @Err 
= 5
    Goto theEnd
    End
Print '更新本栏目下的所有子栏目的:Column_Path,Column_Depth,Column_Order'
             Update Tb_Column Set Column_Path 
= Replace(Column_Path,@oColumn_Path,@nColumn_Path),Column_Depth = Column_Depth + (@nColumn_Depth@oColumn_Depth),Column_Order = Column_Order+( @nColumn_Order@oColumn_Order) Where Column_Path like ''+@oColumn_Path+'|%'
IF @@Error 
<> 0
    Begin
    Set @Err 
= 6
    Goto theEnd
    End
End 
Else
Begin
获取未来父节点的相关信息,并设置本节点的相关值
Select @nColumn_Depth 
= Column_Depth,@nColumn_Path = Column_Path From Tb_Column Where Column_ID =
 @Parent_ID
IF @nColumn_Depth Is  NULL Or @nColumn_Path Is Null
      Begin
      Set @Err 
= 8

      Goto theEnd
      End 
Set @nColumn_Depth 
= @nColumn_Depth +1
Select @nColumn_Order 
=Max(Column_Order) From Tb_Column Where Column_ID = @Paren
 
t_ID Or  Column_Path like 
''+@nColumn_Path+'|%'

IF @nColumn_Order Is  NULL
      Begin
      Set @Err 
= 9
      Goto theEnd
      End 
Set @nColumn_Path 
= @nColumn_Path +'|'+ Ltrim(Str(@Column_ID))
IF @nColumn_Order 
= @oColumn_Order+1 
如果新的父节点是原来位置上端最近一个兄弟,则所有节点的顺序都不改变
                    Begin
Update Tb_Column Set Parent_ID
=@Parent_ID,Column_Path = @nColumn_Path,Column_Depth = @nColumn_Depth, Column_Name = @Column_Name,Column_Intro = @Column_Intro Where Column_ID =
 @Column_ID
IF @@Error 
<> 0

    Begin
    Set @Err 
= 10
    Goto theEnd
    End
       End
Set  @nColumn_Order 
= @nColumn_Order + 1 
更新三部分 1 本树更改之前的后面(或前面)记录的顺序 1 节点本身  3
 所有子节点
分为向上移或象下移
Print '更新本栏目之前位置后面的所有栏目[或者本栏目之后位置]  [不包括本栏目下的子栏目]的:Column_Order'

IF @nColumn_Order 
< @oColumn_Order
Begin
Update Tb_Column Set Column_Order 
= Column_Order+@theCount Where Column_Order<@oColumn_Order  And Column_Order >=@nColumn_Order And (Column_Path Not like ''+@oColumn_Path+'|%') And Column_ID<>
@Column_ID
IF @@Error 
<> 0

        Begin
        Set @Err 
= 12
        Goto theEnd
        End
End
Else
Begin
Update Tb_Column Set Column_Order 
= Column_Order@theCount Where Column_Order >@oColumn_Order And Column_Order<@nColumn_Order  And (Column_Path Not like ''+@oColumn_Path+'|%') And Column_ID<>@Column_ID
IF @@Error 
<> 0

        Begin
        Set @Err 
= 13
        Goto theEnd
        End
End
Print '更新本栏目的:Parent_ID,Column_Path,Column_Depth,Column_Order,Column_Name,Column_Intro'
Print 
'Order : '+Ltrim(Str(@nColumn_Order))
IF @nColumn_Order 
>
 @oColumn_Order
Set @nColumn_Order 
= @nColumn_Order 
 @theCount
Update Tb_Column Set Parent_ID
=@Parent_ID,Column_Path = @nColumn_Path,Column_Depth = @nColumn_Depth,Column_Order = @nColumn_Order, Column_Name = @Column_Name,Column_Intro = @Column_Intro Where Column_ID =
 @Column_ID
IF @@Error 
<> 0

    Begin
    Set @Err 
= 10
    Goto theEnd
    End
Print '更新本栏目下的所有子栏目的:Column_Paht,Column_Depth,Column_Order'
             Update Tb_Column Set Column_Path 
= Replace(Column_Path,@oColumn_Path,@nColumn_Path),Column_Depth = Column_Depth + (@nColumn_Depth@oColumn_Depth),Column_Order = Column_Order+(@nColumn_Order@oColumn_Order) Where Column_Path like ''+@oColumn_Path+'|%'
IF @@Error 
<> 0
    Begin
    Set @Err 
= 11
    Goto theEnd
    End
End
theEnd:
IF @Err
<>0 如果有错误则返回错误号
   Begin
   Rollback Tran
   Return @Err
   End
Else     
如果没有错误就返回0
   Begin
   Commit Tran
   Return 
0

   End
GO

 

存储过程实现无限级分类(3)

最后一步显示分类(只是一条select语句)

Create PROCEDURE sp_Column_List 
 AS
Select Column_ID, Column_Name, Parent_ID, Column_Path, Column_Depth, 
      Column_Order, Column_Intro
FROM Tb_Column
orDER BY Column_Order
GO

接下来就是在界面呈现了 ,    显示的时候用的是DataGrid

Html代码如下:

<asp:DataGrid id="DataGrid1" runat="server" AutoGenerateColumns="False" Width="520px" DataKeyField="Column_Id">
                                
<Columns>
                                    
<asp:TemplateColumn HeaderText="分类信息">
                                        
<ItemTemplate>
                                            
<asp:Label id="lbname" runat="server"></asp:Label>
                                        
</ItemTemplate>
                                        
<EditItemTemplate>
                                            
<asp:TextBox id="tbdgname" runat="server" Text='<%#DataBinder.Eval(Container.DataItem,"Column_Name")%>'>
                                            
</asp:TextBox>
                                        
</EditItemTemplate>
                                    
</asp:TemplateColumn>
                                    
<asp:TemplateColumn HeaderText="添加子节点">
                                        
<ItemTemplate>
                                            
<a href="#" onclick="Open('AddSonCate.aspx?fid=<%#DataBinder.Eval(Container.DataItem,"Column_Id")%>','son',280,80)">添加子分类</a>
                                        
</ItemTemplate>
                                    
</asp:TemplateColumn>
                                    
<asp:TemplateColumn HeaderText="编辑">
                                        
<ItemTemplate>
                                            
<asp:LinkButton runat="server" Text="编辑" CommandName="Edit" CausesValidation="false"></asp:LinkButton>
                                        
</ItemTemplate>
                                        
<EditItemTemplate>
                                            
<asp:LinkButton runat="server" Text="更新" CommandName="Update" CausesValidation="False"></asp:LinkButton>&nbsp;
                                            
<asp:LinkButton runat="server" Text="取消" CommandName="Cancel" CausesValidation="false"></asp:LinkButton>

                                        
</EditItemTemplate>
                                    
</asp:TemplateColumn>
                                    
<asp:TemplateColumn HeaderText="删除">
                                        
<ItemTemplate>
                                            
<asp:LinkButton runat="server" ID="lbdelete" Text="删除" CommandName="Delete" CausesValidation="false" CommandArgument='<%#DataBinder.Eval(Container.DataItem,"Column_Id")%>'>
                                            
</asp:LinkButton>
                                        
</ItemTemplate>
                                    
</asp:TemplateColumn>
                                
</Columns>
                            
</asp:DataGrid>

 

最关键的地方在DataGrid_ItemDataBind事件中

private void DataGrid1_ItemDataBound(object sender, System.Web.UI.WebControls.DataGridItemEventArgs e)
        {
            
if(e.Item.ItemType == ListItemType.Item || e.Item.ItemType ==
 ListItemType.AlternatingItem)
            {
                
//得到Column_Name字段的值

                string columnName = (string)DataBinder.Eval(e.Item.DataItem,    "Column_Name");
                
string columnTemp = ""
;
                
//得到深度值Column_Depth

                int columnDepth = Int32.Parse(DataBinder.Eval(e.Item.DataItem,"Column_Depth").ToString());
                
if(columnDepth>1
)
                {
                    
for(int i = 1;i<columnDepth;i++
)
                    {
                        columnTemp 
+="&nbsp;&nbsp;&nbsp;&nbsp;"
;
                    }
                    columnTemp
+=""
;
                }
                Label lbname 
= (Label)e.Item.FindControl("lbname"
);
                lbname.Text 
= columnTemp+
columnName ;
                LinkButton lbdelete 
= (LinkButton)e.Item.FindControl("lbdelete"
);
                lbdelete.Attributes.Add(
"OnClick","JavaScript:return confirm('确实要删掉此分类吗?');"
);
            }                
        }

[MVC]Free ASP.NET MVC “NerdDinner” Tutorial Now in

mikel阅读(763)

Scott联合几位编写的《Professional ASP.NET MVC 1.0 》在线文档上线了,以下引自Scott的blog:

Last month I blogged about a free end-to-end ASP.NET MVC tutorial called “NerdDinner” that I wrote for the Professional ASP.NET MVC 1.0 book from Wrox Press.  The book is now released and shipping on Amazon

The NerdDinner tutorial walks through how to build a small, but complete, application using ASP.NET MVC, and introduces some of the core concepts behind it.  You can download a PDF version of the tutorial here.

NerdDinner Tutorial Now Also Available in HTML

A few minutes ago I finished publishing an HTML version of the NerdDinner tutorial as well.  You can read it online for free here.

I split the tutorial up across 12 segments to make it more manageable to read.  I also increased the sizes of the screenshots, and used a really nifty syntax highlighter that Scott Hanselman helped set me up with.  I actually find the end result a lot easier to read than the PDF version.

Below are links to the different NerdDinner tutorial segments:

Hope this helps,

Scott

[C#]采访:Chad Myers和FubuMVC - ASP.NET上的另一个MVC实现

mikel阅读(732)

作者 Jon Arild Tørresdal译者 王瑜珩 发布于 2009年4月21日 下午9时51分

社区
.NET
主题
开放源代码,
Web框架
标签
ASP.NET MVC,
FubuMVC,
ASP.NET

ASP.NET MVC 正式版发布前,Jeremy D.MillerChad Myers 就在ASP.NET MVC的早期版本上进行了一些工作,并对底层实现做了一些修改。后来他们改掉了几乎所有的ASP.NET MVC实现,于是决定构造另一个MVC实现FubuMVC ,不久后Mark Nijhof 被邀请加入项目并成为主要成员。

Fubu代表“For us,by us”。现在FubuMVC除了使用ASP.NET Routing外,不使用任何ASP.NET MVC的实现代码,而ASP.NET Routing则已经包含在.NET Framework 3.5 SP1中。

InfoQ的Jon Arild Tørresda询问了Chad Myers,ASP.NET MVC与FubuMVC之间最大的不同是什么:

如果非要选一个,我选择“组合对继承”。这是一个设计上的基本区别,但并不是说ASP.NET MVC的设计不好,只是我认为ASP.NET MVC在类结构设计上倾向于使用继承,因而无法像使用组合那样易于设计动态的Web应用程序。

FubuMVC是一个前端控制器 (Front Controller)框架。Chad指出这个模式的两个主要目标是:

  1. 分离对请求的不同关注点
  2. 允许使用组合的方式构造响应,以发回给客户端

对于前端控制器,Chad解释道:“我们不是不能使用ASP.NET MVC来实现前端控制器,但是这非常的困难”。

在FubuMVC中有很多实现方面的决定,其中之一是在Controller的Action执行前后所执行的“行为”。Chad解释了为什么他们管它叫行为,以及它在FubuMVC中的意义。

当我在一个Virual ALT.NET(VAN)会议上向一些人演示FubuMVC的早期版本时,Steven Harman (http://stevenharman.net)建议我将之称为“行为”,因为这个词语准确描述了所发生的事,我有点喜欢这个名字。

在FubuMVC中,行为的实现方式实际上是装饰模式和职责链模式的混合体。

……

行为对请求管道拥有完全控制权,它可以添加或修改请求,动态选择需要执行的action以及是否要执行action,它可以修改或者完全替换 action的输出结果,并且可以在完成请求处理后执行一些代码。实际上,生成显示结果本身也是一个行为。FubuMVC使用行为本身来实现基本的功能, 这些基本功能和行为可以根据需要被替换或修改。

Mark Nijhof在他的文章FubuMVC and the Front Controller style framework中展示了这个管道:

Request Flow

Chad说,“行为开启了在其他框架中难以实现的可能”:

  • 将整个请求包装在try/catch/finally块中的能力
  • 多级缓存的能力
  • 根据运行时环境或请求时间,动态决定执行哪个action的能力

MVC模式的另一个方面,是使得开发人员可以对传统意义上无法进行测试的UI部分进行单元测试。Chad描述了微软是如何实现这一点的:

……微软在最近对MVC框架的更新中(Beta,RC和最终的发布版)迈出了一大步,相比于Preview 3,对单元测试的支持更好了。但是我仍然认为继承和防备代码的过度使用以及故意不使用接口,使得在ASP.NET MVC中进行测试显得很笨重。

他继续解释了FubuMVC是如何实现这一模式的:

相反,FubuMVC使用简洁的、易于mock的接口,着重于高内聚低耦合的设计。其中,低耦合更成功一些,但这一切仍在开发之中,我希望将来的设计可以提高内聚程度。

FubuMVC高度依赖SOLID原则,这使得它有很高的灵活性,开发人员仅仅使用一个mock就可以替换框架中的整套部件,并且可以使用任何他们喜欢的mock框架。

FubuMVC并没有很多的防御性代码……相反,它将注意力集中在设计提供自由控制的组件上面,这些组建是客户代码主要存在的地方:控制器(controller)、行为、视图(view)以及可以重载的部分。

FubuMVC的类之间几乎没有依赖关系,仅有的依赖也是对接口的依赖,这些接口可以很容易的用mock对象来模拟。

由于项目中有Jeremy(IoC容器StructureMap的创建者),你可能会认为控制反转和IoC容器会得到较多的支持,事实上也确实如此:

目前的版本仅支持StructureMap,但是将来很可能会加入对其他容器的支持。框架对于容器的使用非常少,仅限于在配置时使用。其余的部分利 用容器的自动绑定功能完成,因此基本上没有使用“service location”。对于仅有的一点service location,我们使用微软Patterns and Practices的Common Service Locator进行处理,它可以让我们方便的替换底层依附于CSL模式的IoC容器(多数容器都满足这个条件)。

FubuMVC还有一个contrib project,InfoQ问道相比于FubuMVC的核心框架,这个项目的目标有什么不同:

我们希望能够有更多的自由来发展FubuMVC,因此建立了FubuMVC Contrib。我们想尝试一下插件,这样可以有更多的人参与进来,他们可以在较少的限制下做更多的尝试,同时保持核心框架的稳定。

FubuMVC核心框架将会维持少数几个成员,对待补丁会更谨慎,对框架的修改也会更少。FubuMVC-Contrib将会有更多的参与者、更多 的改动、更低的要求,可能有无法工作的代码或实验性质的代码。当在contrib中开发出有趣的东西后,可以将这些东西合并到核心框架,或者拆分到单独的 项目中。

现今,FubuMVC还没有ASP.NET MVC那样成熟,但是它的实现方式很有趣,这个框架将会如何发展,它与ASP.NET MVC的发展方向将会有怎样的不同,我们将拭目以待。关于FubuMVC的更多信息,可以查看他们的wikiRyan Kelley的从头开始学FubuMVC教程。

原文地址:Interview: Chad Myers on FubuMVC – An Alternative MVC Implementation in ASP.NET

[SVN]更换SVN服务器地址

mikel阅读(693)

有时更换svn服务器地址的时候使代码和工程的联系断了,但是又还有代码没有提交,这时可以手工把工程和svn服务器连起来

郁闷呀,现在找到办法了

查找所有工程下的entries文件,把其中的 http://svnserver/svnroot (svn地址)替换为新的地址

ultraedit的在文件中替换功能太帅了

 

  使用最新版本的TortoiseSVN,右键在工作复本的根目录上右键->TortoiseSVN->重新定位(Relocate),再按提示操作就可以了..不过最好先备份..因为这个操作有一定的危险性