Global.asax ( ASP.NET 或 HTTP 模块所引发的应用程序级别和会话级别事件的代码。继承于HttpApplication。)
HttpApplication.BeginRequest ( 该事件在 ASP.NET 响应请求时作为 HTTP 执行管线链中的第一个事件发生。 )
通过 HttpApplication.BeginRequest 事件 可以简单的实现 Url 重写。
在Global.asax中添加.
protected void Application_BeginRequest(object sender, EventArgs e)
{
// 获取到原始请求链接.
string oldUrl = HttpContext.Current.Request.RawUrl;
/*
在这里根据需要情况加上需要重写。。。
*/
/* 例子一
// 获取到原始请求链接.
string oldUrl = HttpContext.Current.Request.RawUrl;
// 正则表达式获取请求的查询字符串
string pattern = @"^(.+)default/(\d+)\.html(\?.*)*$";
// 正则表达式替换地址和请求的查询字符串
string replace = "$1default.aspx?id=$2";
// 指示正则表达式中是否能找到匹配项
if (Regex.IsMatch(
oldUrl, pattern, RegexOptions.IgnoreCase | RegexOptions.Compiled))
{
// 替换URL地址以便实现重写
string newUrl = Regex.Replace(
oldUrl, pattern, replace, RegexOptions.Compiled | RegexOptions.IgnoreCase);
}
*/
/* 例子二
////将访问的html后缀全部修改成aspx
string newUrl = oldUrl.Replace(".html", ".aspx");
*/
// 指定内部重写路径,并允许请求的 URL 与资源的内部路径不同。
this.Context.RewritePath(newUrl);
}
Webgame ideology
服务器环境:WINNT Server(2003/2008)
发布:IIS6(IIS7
数据库:MSSQL
运行环境:DOTNET3.0
开发环境: Microsoft Visual Studio
*理想运行模式:前台服务器,游戏逻辑服务器,数据库服务器,媒体图片服务器,
*理想采用技术: ASP.NET(C#),javascript,AJAX,Flex/ Silverlight,webService/Wcf,CRL
VSTS+TFS搭配Team的开发环境集中管理
1、
TCP/IP协议,支持Internet、LAN等不同的网络,通过数据压缩和减少数据量的优化方法,重要数据采用客户端(js)加密,服务端(c#)解密,单台服务器承载能力提升到最优,
|
整个系统的结构分为两部分:浏览器即为概念中的客户端;web服务器、逻辑服务器、数据库服务器即为概念中的服务器端。
l Web服务器: web服务器负责界面资源的提供,简单瞬时事件的处理(如招一个兵等),和做为与其它服务器数据交换的接口,web服务器的功能主要由asp.net来开发实现。.添加MIME映射,配置WAP网站,负责移动设备中可触发的事件.,
l 逻辑服务器负责逻辑事件(非瞬时,如资源的增长、一场安排的战争等),主要功能由C#来开发实现,实现的方式为windows服务。性能要求较高函数采用CRL编写提高性能方面,
l 数据库负责存储整个游戏世界的真实数据,包括基础数据表和详细数据表。基础数据表:比如等级1到等级100的用户的属性初始值。详细数据表:每个用户的具体属性。
l 浏览器: 其中客户端只负责游戏界面的展现、操作效果的显示、以及所显示数据的虚假计算(所有数据回发服务器端经过验证才会有效),客户端的功能主要由javascript来开发实现,同时尽可能的使用ajax技术回发服务器
事件系统
事件系统是整个webgame的核心,他保证游戏时间能够24小时运转。事件主要包括两个种类:瞬时事件和逻辑事件。根据游戏的类型不同、设计不同,具体的某个事件(战斗)即可做为瞬时事件,也可以做为逻辑事件,具体描述如下:
2.1瞬时事件
瞬时事件是指玩家发出指令的瞬间就可以完成的事件,如玩家建造一栋建筑,同时扣除相应的木头、石头等资源(或是即时的战斗)。
这部分事件的处理,可由客户端进行虚假处理,包括数据的计算和效果的展示,待提交服务器时(用户触发或定时提交)在服务器端进行数据真实性的验证,验证的方式可以包括数据加密验证、数据计算的逻辑性验证。如通过验证则写入数据库,为通过则把数据库中真实的数据回发给客户端。此部分事件的执行,如数据运算较为简单,则由web服务器执行,如运算量比较大,则调用逻辑服务器的接口进行运算。
2.2逻辑事件
逻辑事件是指非瞬时的事件,是指玩家发出指令后过一段才能执行的事件(安排战争),以及不由玩家触发的,游戏中的自然事件(资源的增长、游戏安排的任务、随即事件等)。
逻辑事件由逻辑服务器来执行计算,暂时考虑的事件方式是,在数据库中建立一张事件队列的表,其中包括事件类型、开始时间、结束时间、玩家信息、城镇信息等,逻辑服务器中运行的服务(C#开发)会定时检查事件队列的未进行的事件,将事件及相关的信息取出进行运算,待运算完成后将结果写入数据库。在玩家访问web服务器时将数据库中信息同步到客户端中。
游戏单元考虑
提供各类城市 建筑队建筑 英雄构造
- 事件消息发送后采用FALASH动画显示,在某段时间后消息回发机制通知玩家
各类英雄相互克制 各类兵种组合带有不同效果 城堡的防护可配置多种
- 逻辑服务器上的判断.数值对抗的平衡
使得各类玩家配合更有趣味 此单元对数值平衡方面需要更细心
游戏行动规则
可采用CTB制(Continued Turn Based,连续行动回合模式),使玩家在保留适度的游戏节奏,可使用动画效果达到更好的用户体验,或采用无过程战斗,玩家发送战斗后在N时间后服务器回发结果消息回发通知,给游戏内定白天黑夜时间 不同的时辰作战对不同的兵种有特别的优势
游戏互动道具
道具编号分配各类属性 此处可考虑道具分为两种
一种为 材料合成道具 采用百分比几率等级累加合成 失败则武器丢失
一种为游戏内定商场事前购买的道具将以玩家在游戏中获得的金钱作为交换,在游戏大厅的商店中购得、并装备在玩家的道具栏中,
战友同盟
游戏中将为玩家提供人为组织机制,使志趣相投的玩家可以拥有自己独立的交流大厅,并可以在游戏中行使战队专用BBS、战队专用聊天频道、战队专有内部职务/权能等等功能;战队同盟之间可以相互交流,并可以进行大规模的团队战斗,聊天系统采用
delete table
DELETE (Transact-SQL)
DELETE 语句可删除表或视图中的一行或多行。
DELETE 语法的简化形式为:
DELETE table_or_view
FROM table_sources
WHERE search_condition
参数 table_or_view 指定要从中删除行的表或视图。table_or_view 中所有符合 WHERE 搜索条件的行都将被删除。如果没有指定 WHERE 子句,将删除 table_or_view 中的所有行。FROM 子句指定可由 WHERE 子句搜索条件中的谓词使用的其他表或视图及联接条件,以限定要从 table_or_view 中删除的行。不会从 FROM 子句指定的表中删除行,只从 table_or_view 指定的表中删除行。
任何已删除所有行的表仍会保留在数据库中。DELETE 语句只从表中删除行,要从数据库中删除表,可以使用 DROP TABLE 语句。
TRUNCATE TABLE (Transact-SQL)
若要删除表中的所有行,则 TRUNCATE TABLE 语句是一种快速、无日志记录的方法。TRUNCATE TABLE 与不含有 WHERE 子句的 DELETE 语句在功能上相同。但是,TRUNCATE TABLE 速度更快,并且使用更少的系统资源和事务日志资源。
与 DELETE 语句相比,TRUNCATE TABLE 具有以下优点:
与 DELETE 语句相同,使用 TRUNCATE TABLE 清空的表的定义与其索引和其他关联对象一起保留在数据库中。
由于上一次设计感觉还是太繁琐 所以重新考虑了架构 感觉利用C#委托也可以达到同样的效果。首先我们复习下之前的观察者模式概念和原则 然后还是以气象监测应用系统演示。
观察者模式(Observers) 定义了对象之间的一对多依赖,这个一来,当一个对象改变状态时,它所有的依赖者都会收到通知并自动更新,主题和观察者定义了一对多的关系 观察者依赖于主题,只要主题状态一有改变,观察者就会接受到通知 根据通知的风格;
当两个对象之间松耦合,它们依然可以交互,但不太清除彼此的细节。观察者模式提供了一种对象设计,让主题和观察者之间松耦合。主题只知道观察者实现了某个接口(也就是Observer接口)主题不需要知道观察者的具体类是谁,做了些什么或其他的任何细节。任何时候我们可以添加新的观察者。因为主题唯一依赖的东西是一个实现Observer接口的对象列表。
松耦合的设计之所以能让我们建立有弹性的OO系统,能够应对变化,是因为对象之间的互相依赖降到了最低。所以我们为了交互对象之间的松耦合设计而在努力。
Demo - 气象监测应用系统
气象观测局专利申请在WeatherData对象中,由WeatherData负责追踪天气状态。成功以后以供布告板显示,由可能很多不同的布告板,每个布告板的显示都有所不同,并且当Weather对象得到新的数据时,所有布告板都必须更新。
namespace Exercise.BureauOfMeteorology
{
class WeatherData
{
public delegate void UpdateDisplay(object sender, args e);
public event UpdateDisplay UpdateEvent;
public void SetMeasurements(float t, float h, float p)
{
args e = new args(t, h, p);
Console.WriteLine("Began to inform all observers ..");
if (UpdateEvent != null)
{
UpdateEvent(this, e);
}
Console.WriteLine("End to all observers ..");
}
public class args : EventArgs
{
private float temperatrue;
public float Temperatrue
{
get { return temperatrue; }
set { temperatrue = value; }
}
private float humidity;
public float Humidity
{
get { return humidity; }
set { humidity = value; }
}
private float pressure;
public float Pressure
{
get { return pressure; }
set { pressure = value; }
}
public args(float t, float h, float p)
{
this.temperatrue = t;
this.humidity = h;
this.pressure = p;
}
}
}
}
namespace Exercise.BureauOfMeteorology.Display
{
class CurrentConditions
{
public CurrentConditions(WeatherData weatherData)
{
weatherData.UpdateEvent += new WeatherData.UpdateDisplay(Display);
}
public void Display(object sender, WeatherData.args e)
{
Console.WriteLine(
"CurrentConditions : " + e.Temperatrue +
" F degrees and " + e.Humidity + "% humidity");
}
}
}
namespace Exercise.BureauOfMeteorology.Display
{
class Forecast
{
public Forecast(WeatherData weatherData)
{
weatherData.UpdateEvent += new WeatherData.UpdateDisplay(Display);
}
public void Display(object sender, WeatherData.args e)
{
Console.WriteLine(
"Forecast : " + e.Temperatrue +
" F degrees and " + e.Humidity + "% humidity");
}
}
}
Exchange for Strategy
朱天业 17:18:35
我觉得策略模式是指把 方法列出来,然后用里面的一个或多个方法去拼装对象。
.. 17:19:23
我怎么理解成替换对象?
.. 17:19:28
相互交替?
朱天业 17:31:02
对
朱天业 17:31:34
将具体实现延迟到子类中实现,那个是什么模式去了?
.. 17:33:42
工厂这几天我正在看
.. 17:33:57
工厂方法不算模式的一种 却只是一个编程习惯
朱天业 17:35:12
模式就是大家都比较认可的、便于交流和学习的一些设计方法。
.. 17:35:32
但是你必须知道每个模式的核心。
.. 17:35:39
比如策略模式 他是交替对象的
.. 17:35:58
你要有这个意识 然后参考着
.. 17:36:02
设计。
.. 17:36:35
你想 每个武器都可以相互替换 不同的角色。。
对武器的扩展 和角色的扩展 和调用 都达到了很好的效果
.. 17:37:12
无论什么角色使用什么武器 在操作的时候你可以随意调用对象 我觉得这就是策略模式的精髓
朱天业 17:37:13
但是有一点你要知道,法师用法杖,山丘不能用
.. 17:37:28
这只是一个比方。。。
.. 17:37:38
假设我们把武器换成4个算法
.. 17:37:59
角色换成了调用的规则 这样的话套上去 就应该是了
朱天业 17:37:59
而且我觉得这个的粒度在方法,不在对象。
.. 17:38:23
他只是把行为的方法当成了对象
.. 17:39:18
而且做到了针对超类型编程
.. 17:39:23
也就是针对接口编程
朱天业 17:39:57
哈哈,先问下你这个是面向对象还是面向业务的?
.. 17:40:39
在武器内的绘画 其实就是不同的算法 分别封装起来 让他们可以互相替换 让算法的变化独立于使用算法的对象
.. 17:40:49
面向接口
.. 17:40:54
其实就是面向对象
.. 17:40:58
应该是这么说的
.. 17:42:19
封装 继承 多态 抽象 这些只是OO的基础
.. 17:42:40
而设计模式就是别人的经验 你看完后对这样的设计要有这样的意识
.. 17:43:14
做到了业务跟着程序走 而不是 程序跟着业务走
因为我们的开始都在面向实现编程。
.. 17:43:16
- -。
朱天业 17:43:50
你入魔了。
.. 17:44:03
..........
.. 17:45:26
我们必须做到 程序具有弹性的设计 维护 可以应付变化
.. 17:45:36
这样才叫程序
.. 17:46:13
而每个设计模式都有些原则 在编写的时候多想想这些原则 会有帮助
.. 17:46:53
而策略模式讲了一个重点 那就是 多用组合 少用继承
.. 17:47:10
哎 我看一个模式就看了1个月 我不入魔才怪。
朱天业 17:50:32
你用这种心态去看:
一、设计模式是为了利于程序员之间交流
二、借鉴前人已有经验,构建更健硕的程序
大哥的话:“不要为了套模式而用模式”
.. 17:50:52
是啊 但是每个模式会有设计原则
.. 17:50:57
而不是使用模式。
朱天业 17:51:35
我们已经用过很多的模式,只是没有归纳总结。
.. 17:51:41
比如说 针对接口编程 也不是针对实现编程。。
.. 17:51:53
多用组合 少用继承
.. 17:52:24
找出应用中可能需要变化之处 把他们独立出来 不要和那些不需要变化的代码混在一起。
.. 17:52:47
这是策略模式的设计原则。
Design Patterns - Observers
观察者模式(Observers) 定义了对象之间的一对多依赖,这个一来,当一个对象改变状态时,它所有的依赖者都会收到通知并自动更新,主题和观察者定义了一对多的关系 观察者依赖于主题,只要主题状态一有改变,观察者就会接受到通知 根据通知的风格;
当两个对象之间松耦合,它们依然可以交互,但不太清除彼此的细节。观察者模式提供了一种对象设计,让主题和观察者之间松耦合。主题只知道观察者实现了某个接口(也就是Observer接口)主题不需要知道观察者的具体类是谁,做了些什么或其他的任何细节。任何时候我们可以添加新的观察者。因为主题唯一依赖的东西是一个实现Observer接口的对象列表。
松耦合的设计之所以能让我们建立有弹性的OO系统,能够应对变化,是因为对象之间的互相依赖降到了最低。所以我们为了交互对象之间的松耦合设计而在努力。
Demo - 气象监测应用系统
气象观测局专利申请在WeatherData对象中,由WeatherData负责追踪天气状态。成功以后以供布告板显示,由可能很多不同的布告板,每个布告板的显示都有所不同,并且当Weather对象得到新的数据时,所有布告板都必须更新。
namespace Exercise.BureauOfMeteorologyBackup
{
/// <summary>
/// 主题的接口
/// </summary>
interface ISubject
{
/// <summary>
/// 登记观测者
/// </summary>
/// <param name="o"></param>
void RegisterObserver(IObserver o);
/// <summary>
/// 移除观察者
/// </summary>
/// <param name="o"></param>
void RemoveObserver(IObserver o);
/// <summary>
/// 通知观察着
/// </summary>
/// <!--
/// 当主题状态改变时这个方法会被调用 以通知所有的观察者 -->
void NotifyObservers();
}
class WeatherData : ISubject
{
/// <summary>
/// <!-- 使用ArrayList的形式来记录观察者 -->
/// </summary>
private ArrayList observers;
private float temperature;
private float humidity;
private float pressure;
public WeatherData(){
observers = new ArrayList();
}
#region ISubject 成员
/// <summary>
/// 当注册观察者时 只需要添加到ArrayList后面即可
/// </summary>
/// <param name="o"></param>
public void RegisterObserver(IObserver o)
{
observers.Add(o);
}
/// <summary>
/// 当取消注册的时只需要从ArrayList移除即可
/// </summary>
/// <param name="o"></param>
public void RemoveObserver(IObserver o)
{
int i = observers.IndexOf(o);
if (i >= 0){
observers.Remove(i);
}
}
/// <summary>
/// 通知所有观察者新的状态
/// </summary>
public void NotifyObservers()
{
for (int i = 0; i < observers.Count; i++){
IObserver observer = (IObserver)observers[i];
observer.Update(temperature, humidity, pressure);
}
}
#endregion
/// <summary>
/// 当从气象局得到更新观测值时 通知所有观察者
/// </summary>
public void MeasurementsChanged(){
NotifyObservers();
}
public void SetMeasurements(float temperature, float humidity, float pressure)
{
Console.WriteLine("Began to inform all observers ..");
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
MeasurementsChanged();
Console.WriteLine("End to all observers ..");
}
}
}
namespace Exercise.BureauOfMeteorologyBackup
{
/// <summary>
/// <!-- 所有的气象局组件都实现此观察者接口 主题在需要通知观察者时 有一个共同的接口 -->
/// </summary>
interface IObserver
{
/// <summary>
/// <!-- 当气象局观测值改变时 主题会把这些状态值当作方法的参数 传递给观察者 -->
/// </summary>
void Update(float temperature, float humidity, float pressure);
}
interface IDisplayElement
{
/// <summary>
/// 当布告板需要显示时 调用此方法
/// </summary>
void Display();
}
}
namespace Exercise.BureauOfMeteorologyBackup.Display
{
class CurrentConditions: IObserver ,IDisplayElement
{
private float temperature;
private float humidity;
private ISubject weatherData;
public CurrentConditions(ISubject weatherData)
{
this.weatherData = weatherData;
weatherData.RegisterObserver(this);
}
#region IDisplayElement 成员
/// <summary>
/// 显示最近的温度和湿度
/// </summary>
public void Display()
{
Console.WriteLine(
"Current conditions : " + temperature +
" F degrees and " + humidity + "% humidity");
}
#endregion
#region IObserver 成员
/// <summary>
/// 温度和湿度保存然后显示
/// </summary>
public void Update(float temperature, float humidity, float pressure)
{
this.temperature = temperature;
this.humidity = humidity;
Display();
}
#endregion
}
}
namespace Exercise.BureauOfMeteorologyBackup.Display
{
class Forecast:IObserver,IDisplayElement
{
private float temperature;
private float humidity;
private WeatherData weatherData;
public Forecast(WeatherData weatherData)
{
this.weatherData = weatherData;
weatherData.RegisterObserver(this);
}
#region IObserver 成员
public void Update(float temperature, float humidity, float pressure)
{
this.temperature = temperature;
this.humidity = humidity;
Display();
}
#endregion
#region IDisplayElement 成员
public void Display()
{
Console.WriteLine(
"Forecast : " + temperature +
" F degrees and " + humidity + "% humidity");
}
#endregion
}
}
策略模式(Strategy Pattern)属于对象行为型模式,体现了两个非常基本的面向对象设计的基本原则:封装变化的概念;编程中使用接口,而不是对接口实现。策略模式的定义如下:
定义一组算法,将每个算法都封装起来,并且使它们之间可以互换。每一个算法封装到具有共同接口的独立的类中,策略模式使这些算法在客户端调用它们的时候能够互不影响地变化。
策略模式使开发人员能够开发出由许多可替换的部分组成的软件,并且各个部分之间是弱连接的关系。弱连接的特性使软件具有更强的可扩展性,易于维护;
策略模式中有三个对象:
(1) 环境对象:该类中实现了对抽象策略中定义的接口或者抽象类的引用。
(2) 抽象策略对象:它可由接口或抽象类来实现。
(3) 具体策略对象:它封装了实现同不功能的不同算法。
利用策略模式构建应用程序,可以根据用户配置等内容,选择不同有算法来实现应用程序的功能。具体的选择有环境对象来完成。采用这种方式可以避免由于使用条件语句而带来的代码混乱,提高应用程序的灵活性与条理性。
我们先用一个简单的例子开始. 一个实现游戏中的更换武器的场景。游戏中的每个角色配对一个武器。当然武器是可以随便更换的。。其中定义了角色的抽象,武器的抽象接口。
Heroes(角色)抽象类 定义了 角色名称属性, 武器接口,更换武器的函数,一个虚方法为更换武器的过程。
public abstract class Heroes
{
public string HeroesName;
protected IWeaponBehavior weapon;
public void setWeapon(IWeaponBehavior w) { this.weapon = w; }
public virtual void Fight()
{
throw new Exception(" this method should be Rwritten");
}
}
// 大法师
public class ArchMage : Heroes
{
public ArchMage()
{
this.HeroesName = "法师";
}
public override void Fight()
{
Console.Write(this.HeroesName);
this.weapon.useWeapoon();
}
}
通过以下步骤,开发人员可以很容易地在软件中实现策略模型:
1.对策略对象定义一个公共接口。
2.编写策略类,该类实现了上面的公共接口。
3.在使用策略对象的类中保存一个对策略对象的引用。
该武器为公告接口,具体的共有4种不同的武器(策略类 实现了公共接口) 其中都实现了各自武器的绘画..
// 武器接口
public interface IWeaponBehavior
{
void useWeapoon();
}
// 实现用宝剑挥舞
public class SwordBehavior : IWeaponBehavior
{
public void useWeapoon()
{
Console.Write(" 宝剑挥舞 ");
}
}
// 实现匕首刺杀
public class KnifeBehavior : IWeaponBehavior
{
public void useWeapoon()
{
Console.Write(" 匕首刺杀 ");
}
}
// 实现用弓箭刺杀
public class BowAndArrowBehavior : IWeaponBehavior
{
public void useWeapoon()
{
Console.Write(" 弓箭刺杀 ");
}
}
// 实现用斧头砍杀
public class AxBehavior : IWeaponBehavior
{
public void useWeapoon()
{
Console.Write(" 斧头砍杀 ");
}
}
程序中调用...
Console.WriteLine("a 宝剑 b 匕首 c 弓箭 d 斧头");
while (true)
{
Heroes hr = new ArchMage();
IWeaponBehavior iwb = GetWeaponBehavior();
hr.setWeapon(iwb);
hr.Fight();
}
// 获得选择的武器...
static IWeaponBehavior GetWeaponBehavior()
{
while (true)
{
string userOperation = Console.ReadLine();
if (string.Equals(userOperation, "a"))
{
return new SwordBehavior();
}
if (string.Equals(userOperation, "b"))
{
return new KnifeBehavior();
}
if (string.Equals(userOperation, "c"))
{
return new BowAndArrowBehavior();
}
if (string.Equals(userOperation, "d"))
{
return new AxBehavior();
}
}
}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>无标题页</title>
<script type="text/javascript" language="javascript">
function AddCountry(thisform)
{
var arr = new Array("中国","阿尔及利亚","阿根廷","阿拉伯联合酋长国","阿曼","阿松森");
for(var i=0;i<arr.length;i++)
{
thisform.country.options.add(new Option(arr[i], arr[i]));
}
}
function MinusAllList(col)
{
while (col.length>1)
{
col.options.remove(1);
}
}
function flush(thisform)
{
var pro = new Array("北京","上海","天津","重庆","安徽","福建","甘肃","广东","广西","贵州","海南","河北",
"河南","黑龙江","湖北","湖南","吉林","江苏","江西","辽宁","内蒙古","宁夏","青海","山东",
"山西","陕西","四川","西藏","新疆","云南","浙江","香港","澳门","台湾");
var agt = new Array("阿根廷城市","阿根廷乡下","阿根廷地区")
thisform.city.options.length = 0;
thisform.city.options.add(new Option('请选择', '0'));
if(thisform.country.value == '中国')
{
for(var i=0;i<pro.length;i++)
{
thisform.city.options.add(new Option(pro[i], pro[i]));
}
thisform.city.disabled = false;
}
else if(thisform.country.value == '阿根廷')
{
for(var i=0;i<agt.length;i++)
{
thisform.city.options.add(new Option(agt[i], agt[i]));
}
thisform.city.disabled = false;
}
else
{
MinusAllList(thisform.city);
thisform.city.disabled = true;
}
}
</script>
</head>
<body>
<form id="thisform" runat="server">
<div>
<select name="country" class="w13" onchange="flush(thisform);">
<option selected="selected" value='0'>请选择国家或地区</option>
</select>
<script type="text/javascript">AddCountry(thisform);</script>
<select name="city" class="w13">
<option selected="selected" value="0">请选择省市区</option>
</select>
</div>
</form>
</body>
</html>
图形图像支持
.Net图像处理如,GDI+,WPF & Silverlight,提供了非常方便的处理方法,可以用于快速搭建用户界面。
DirectX 是Windows平台强大的图形处理库。可以用于2D,3D。从众多游戏中可以领略其性能。.Net中有接口可以在.Net环境中基于DirectX开发。
同样的原理,我们也可以在.Net中调用C++编写的Dll,这种技术的名称叫做P/Invoke.
MVC框架
MVC,指Model、View和Controller。是一种将数据层和表现层进行分离的设计模式/框架,简单来说,由Model层建立数据模型,由Controller层取得数据,并控制由哪个表示层展示数据,由View层负责数据展示。普通的系统,数据层的代码和表示层的代码混杂,不利于维护。分离后,数据层可以相对稳定,表示层则可以随意变化,甚至对应多个表示层。这便于将数据层和表示层分给两个不同的开发人员来完成,避免对所有开发人员都提出很熟悉系统的要求,便于新成员融入团队。
VSTS && MSF
MSF是一套解决软件开发流程的解决方案(类似于RUP等),它可以知道你在软件生命周期中的开发流程。
而VSTS是开发工具,一般来说,VSTS+TFS这样来搭配Team的开发环境,这样就可以集中管理,TFS里面可以导入msf 相应的过程模板,或者自定义软件过程模板
UML是我们在做分析设计时候不可缺少的工具
一定要明确软件工程的过程,也就是说我们在概念模型设计的时候需要用到use-case.从而根据usecase去分析设计逻辑模型,部署模型,流程图等等,在物理设计的时候再过渡到详细的类图,时序图等等,再转换成为开发的框架代码,这是一个平滑的过程,不能弄混,每种东西要用在何时的地方。
SOA
SOA的讨论。随着XML Web Service技术的普及,关于SOA的讨论逐渐平息下来。
继SOA之后,现在SaaS和S+S两个概念非常引人关注,微软也在这方面有不小投入。目前已经有一个基于.Net 3.0的SaaS中文应用案例发布1.0版本。请参考http://www.cnsaas.com/
当你要做很大的分布式系统的时候就可以体现SOA的价值了,比如一个集团有很多系统,在不同的地方,有在北京的,有在西藏的还有在国外的,每个系统功能都不一样
你所做的web系统需要去访问这些系统,取不同的东西,那么这就可以使用soa来设计,每个系统都提供一个services,你去调用,但是怎么调用呢,那就要根据每个serivices的情况去选择协议,比如你用webservices,你用msqueue等等可以先学习一下WCF,然后试着去写分布式web系统。
开发应用在多内核环境下的系统软件
多线程在.Net中支持是很强大的。
在VS2008种可以中断进程,在每个线程中切换,观察不同线程中变量的状态。
如果是编写多进程的并行程序,可以使用MPI。MPI是在C中的一个并行通讯标准。微软有MPI的实现,包含在WCCS2003,Windows HPC Server2008的SDK中。可以免费下载。
现在还有一个MPI.Net的项目。可以参考。
http://www.osl.iu.edu/research/mpi.net/
Visual Studio同时支持C#,C++,C等多种语言,对于开发人员是很方面便的。
线程
在单机中的并发主要要注意线程安全问题。
在.Net每个类的帮助文件中,都会有线程安全的说明。在编写多线程程序的时候,要仔细阅读。
服务器的并发问题比较复杂。在写程序的时候注意及时释放资源,避免形成死锁。
WIN208 SERVER
WIN08”命令模式,而是一种新的选择。WIN08支持按需安装的原则,如,对于文件服务器,则只需要最基本的组件即可实现,这就是您提到的命令模式。这样做的好处是安装最少的组件,可以最小化地带来被攻击的可能,同时避免不停的打一些无关的SP。因此,如果作为ASP.NET的服务器,则可能更加安全。虚拟化则可以更大限度的利用现有的服务器资源,防止资源浪费。同时,不同的程序安装于不同的虚拟服务器上,也避免了因为一个程序出问题而导致整个服务器出问题的情况。
VS08 .net3.5 版本技术添加
3.0 = 2.0 + WPF + WCF + WF + CardSpace
3.5 = 3.0 + LinQ + Silverlight + 其他
3.5 = 2.0 + WPF + WCF + WF + CardSpace + LinQ + Silverlight + 其他
平台兼容
.Net Framework 3.5,3.0都是在2.0基础上的扩展。 所以3.5和3.0的环境下都兼容2.0 的项目。
服务器安装了.Net framework 3.5后可以运行2.0,3.0和3.5的程序。
VS2008中的 "企业级"
我认为体现“企业级”,有很多方面,其中一个很重要的方面是对其它系统的集成。比如,Silverlight可以直接调用原有的Web Service,而不必要重新采用新的语言开发一次。比如,VS08对各种开发技术的整合。再比如:SharePoint对现有各个系统可以进行很好的整合。等等。
AJAX
ASP.Net AJAX Toolkit中包含大量的 AJAX控件。可以从http://www.asp.net/ajax/ 下载或在线体验这些控件
已经集成在Vs08中,SP1已支持AJAX History 增加了JavaScript提示,并且能提示WebServics的名称和他的函数,而且能调试
Remoting
构建分布式应用程序 使用TCP,HTTP多种协议发送文本或二进制的数据,局域网使用较多
webservice
远程调用技术 基于HTTPj交换XML数据 交互能力强 不同的开发语言可以互调 INTERNET 使用广泛
WCF
基于SOA微软提供的安全的解决方案 提供更强大的交互性。完全通过修改配置文件就可以更换不同通信协议,非常方便。有一统Remoting和Web Service 的趋势。WCF的前身是.NET Remoting。Web Service在今天,乃至以后仍将会大量存在。但建议新系统采用WCF技术,它的配置化的设置功能还是比较容易控制些。WCF的优势在于灵活,可配置。而且在3.5种可以支持JavaScript,AJAX代码调用,因为支持JSON。WCF作为一种新技术,让团队中所有人员掌握还是需要时间成本的。
Linq
LINQ是会在运行时生成SQL语句。但这些SQL语句都是经过微软专家优化的,在数据量小时,它的性能比较弱(但这时性能问题没必要考虑),在数据量很大的情况下,它的优势就能体现出来。
LINQ采用了一些反射机制,如下面的方式,实现了一个批量删除的LINQ。
public static int Delete(this IQueryable query)
{
DataContext context = query.GetType().GetField("context", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(query) as DataContext;
var table = (from TableAttribute attribute in typeof(TEntity).GetCustomAttributes(typeof(TableAttribute), false)
select attribute).Single();
// Get Condition
string conditions = string.Empty;
var keys = from property in typeof(TEntity).GetProperties()
from ColumnAttribute attribute in property.GetCustomAttributes(typeof(ColumnAttribute), false)
where attribute.IsPrimaryKey == true
select new { Property = property, Column = attribute };
foreach (var key in keys)
{
conditions = conditions + string.Format("[D0].{0} = [D1].{1}", key.Property.Name, key.Property.Name) + " AND ";
}
conditions = conditions.Remove(conditions.Length - " AND ".Length);
// Get SQL
string sql = string.Format("DELETE FROM {0} FROM {1} AS [D0] INNER JOIN ({2}) AS [D1] ON ({3})", table.Name, table.Name, query.ToString(), conditions);
DbParameterCollection parameters = context.GetCommand(query).Parameters;
for (int i = 0; i
return context.ExecuteCommand(sql);
}
LINQ中,可以直接使用语法进行分页:.Skip(m).Take(n)。另外,您也可以使用新的DataPager控件来简单的实现分页。
Lambda表达式
它提供了完成相同目标的更加简洁的格式。请看下面的代码,在实现了这个扩展方法后,我们已经不需要引用System.Linq这个Namespace了。
var results = source.Where(item => item.Name.Length >= 4);
//var results = source.Where(
// delegate(User item)
// {
// return item.Name.Length >= 4;
// }
// );
public static class LambdaExtensions
{
public static IEnumerable Where(this IEnumerable source, Func filter)
{
foreach (var item in source)
{
if (filter(item) == true) yield return item;
}
}
}
使用Lambda表达式时,注意不要有太多语句写在同一行代码中的情况。如果有嵌套很多层函数的情况,请先定义一个变量,将嵌套的计算结果保持在变量中,然后在LINQ中使用这个变量。如果不这么做,在太多层函数嵌套的情况下,LINQ有可能无法解析。对于没有提供的Lambda表达式,您可以开发自定义的Lambda表达式。
匿名委托
.NET2.0中,匿名方法允许开发者在线声明自己的函数代码而无须使用委托函数(delegate function)。
在LINQ中,现在的委托变得很简单,也很让人一下子看不明白。如下:
var results = source.Where(item => item.Name.Length >= 4);
而在此之前,上面的语句等同于下面的语法:
var results = source.Where(
delegate(User item)
{
return item.Name.Length >= 4;
}
Extension Methods
自己定义的变量续函数,实际上等价于静态类中方法调用,它们两者编译出来的IL是一样的。但有一个建议:如果能实现普通类、方法时,请不要使用Extension Methods,毕竟静态类太多了会引起性能问题。另外,建议不要将太多跟业务相关的方法做成扩展方法,否则会导致很混乱的静态类的引用,这对性能也是一个不小的影响。
工作流
一般来说,我们可以将工作流Host到Web Service中,以便前端的系统调用。如果一定要说在WEB下的工作流,现在有一个新的技术,叫做Pageflow,用于控制页面如何跳转,避免页面至今繁杂、混乱、嵌套的页面流转,这个倒是很值得研究一番。
LINQ && 存储过程 && 扩张存储过程 && CRL
存储过程、使用LINQ to SQL、SQL Command、CLR等方法访问数据。存储过程和CLR都是经过预编译的,性能方面最佳。使用SQL Command传入SQL语句的方法是性能方面最不推荐使用的。而LINQ to SQL,实际上是执行一段SQL语句,因此,理论上性能也高不到哪里去。但是,由于LINQ to SQL生成的SQL语句是由微软专家经过最佳优化的,在数据量很小时,也许所有方案都比较快,但当数据量很大时,微软专家的这些优化的SQL的性能优势就显露出来了。另外,从开发成本来说,LINQ to SQL也是最佳的选择。
良好的封装..
尽可能地限制类和成员的可访问性
采用最严格且可行的访问级别,也就是"采用哪种方式能最好地保护接口的完整性?"
不要公开暴露成员数据,这样会破坏封装性
避免把似有的实现细节放入类的接口中,如果你做到封装,哪么应该是根本就看不到任何封装
不要对类的使用者做出任何假设,类的设计和实现应该符合在类的接口中所隐含的契约
避免使用友元类,虽然有些场合上,比如State模式中使用可以有助于管理复杂度,但友元类会破坏封装性
不要因为一个子程序仅使用公用的子程序,就把它把归入公开接口
让阅读代码比编写代码更容易。
要格外警惕从语义上破坏封装性。
留意过于紧密的耦合关系。这样关联越松越好,这也是平时所说的低耦合。
ADT - Abstract data Type (数据抽象类型)
一些数据以及对这些数据所进行的操作的集合...
首先我觉得必须理解什么是抽象..
为什么抽象不能实例化...
这概念源于还有虚方法...
比如 你游戏系统中有很多的动物.
抽象数据可以让你像现实世界中一样的操作实体.
动物就是一个抽象..它并不是一个实际东西. 只有一个归类..
那么这个抽象下 具体使用也就是能实例化 比如 猫啊. 狗啊. 猪啊..
他们都是单独类.但是他们有共同的属性 和方法..
比如 它们都会叫. 它们都会跑. 它们都有手.它们都有脚..等等..
这不能不说到抽象中的虚方法 该方法并不具备任何实际动作..
但是被重写后具有实际的操作...
使用这样的思想去编写程序会有什么什么好处呢..
可以隐藏实现的细节
改动不会印象到整个程序
让接口能提供更多的信息.
更容易提高性能.
让程序的正确性更显而易见..
程序更具有自我说明..
无需在程序内到处传递数据..
你可以像在现实世界中那样操作实体.而不在底层实现上操作它..
那么在使用的时候有些什么建议..
把常用的底层数据类型创建为ADT并使用这些ADT,而不再使用底层数据类型
把像文件这样的常用对象当成ADT..
简单的事务也可当做ADT
不要让ADT依赖于其存储介质.
抽象的概念来源于类...
在编写程序的时候可能会编写很多很多的类...
但是你的类真的是类吗 你做到了这些吗
一定要理解类所实现的抽象是什么.
提供成对的服务..
把不相关的信息转移到其他类..
尽可能让接口可编程,而不是表达语义..
慎防在修改时破坏接口的抽象
不要添加于接口抽相爱难过不一致的公用成员.
using System;
using System.IO;
using Microsoft.Office.Interop.Word;
using @MSWord=Microsoft.Office.Interop.Word;
namespace Exercise.Office
{
class Program
{
static void Main()
{
// 通过反射产生一个函数的默认参数
object Nothing = System.Reflection.Missing.Value;
// 保存路径和DOC文件名称]
string wordName = "C:\\" + DateTime.Now.ToString("yyyymmddhhmmss") + ".doc";
#region " 创建新文档 .."
Application wordApp = new ApplicationClass();
if (File.Exists(wordName)) File.Delete(wordName);
Document wordDoc = wordApp.Documents.Add(ref Nothing, ref Nothing, ref Nothing, ref Nothing);
#endregion
#region " 设置页眉 .. "
wordApp.ActiveWindow.View.SeekView = WdSeekView.wdSeekPrimaryHeader;
wordApp.ActiveWindow.ActivePane.Selection.InsertAfter("[页眉内容]");
wordApp.Selection.ParagraphFormat.Alignment = WdParagraphAlignment.wdAlignParagraphRight;
wordApp.ActiveWindow.View.SeekView = WdSeekView.wdSeekMainDocument;
#endregion
#region " 设置文档内容 .."
// 设置文档的行间距
wordApp.Selection.ParagraphFormat.LineSpacing = 15f;
wordDoc.Paragraphs.Last.Range.Text = "[文档内容]";
// 创建一个两行三列 表格..
Table newTable = wordDoc.Tables.Add(wordApp.Selection.Range, 2, 3, ref Nothing, ref Nothing);
// 设置宽
newTable.Columns[1].Width = 20f;
newTable.Columns[2].Width = 50f;
newTable.Columns[3].Width = 100f;
// 设置表格内容
newTable.Cell(1, 1).Range.Text = "这是第一行第一列的内容";
newTable.Cell(1, 1).Range.Font.Color = WdColor.wdColorRed;
// 设置字体粗体
newTable.Cell(1, 1).Range.Bold = 2;
// 设置合并单元格
newTable.Cell(1, 1).Merge(newTable.Cell(1, 3));
// 设置垂直居中
wordApp.Selection.Cells.VerticalAlignment = WdCellVerticalAlignment.wdCellAlignVerticalCenter;
// 设置水平居中
wordApp.Selection.ParagraphFormat.Alignment = WdParagraphAlignment.wdAlignParagraphCenter;
// 设置第二行内容
newTable.Cell(2, 1).Range.Text = "这是第二行第一列";
newTable.Cell(2, 2).Range.Text = "这是第二行第二列";
newTable.Cell(2, 3).Range.Text = "这是第二行第三列";
wordDoc.Paragraphs.Last.Range.Text = "文档创建时间:" + DateTime.Now;
wordDoc.Paragraphs.Last.Alignment = WdParagraphAlignment.wdAlignParagraphRight;
#endregion
_Document doc = wordDoc;
object objName = wordName;
doc.SaveAs
(
ref objName,
ref Nothing,
ref Nothing,
ref Nothing,
ref Nothing,
ref Nothing,
ref Nothing,
ref Nothing,
ref Nothing,
ref Nothing,
ref Nothing,
ref Nothing,
ref Nothing,
ref Nothing,
ref Nothing,
ref Nothing
);
doc.Close(ref Nothing, ref Nothing, ref Nothing);
_Application app = wordApp;
app.Quit(ref Nothing, ref Nothing, ref Nothing);
Console.Write("ok..");
Console.Read();
}
}
}
1,FCKeditor 编辑器
最新版本: 2.3.1
演示:http://www.fckeditor.net/ /demo
特点:开源、免费
2,eWebEditor在线编辑器
最新版本:4.0
演示:http://ewebeditor.webasp.net/demo.asp
特点:国产、易用
3,InnovaStudio WYSIWYG Editor在线编辑器
注:WYSIWYG是What You See Is What You Get(所见即所得)首字母组合
最新版本:2.9.7
站点:http://www.innovastudio.com/editor.asp
演示: http://www.innovastudio.com/editor_tutorial.asp
特点: 物有所值
4,Tinymce在线编辑器
最新版本:2.0.6.1
站点:http://tinymce.moxiecode.com/
演示:http://tinymce.moxiecode.com/ /example_full.php?example=true
有关如上4款在线编辑器的测试比较,经典论坛有份帖子,可以参阅下:
http://bbs.blueidea.com/viewthread.php?tid=2621172
5,XStandard
最新版本:1.7.1
特点:支持XHTML+CSS
说明:XStandard Lite免费,XStandard Pro30天试用
6,Free TextBox在线编辑器
最新版本:3.1.6
=======================
Cute Editer
http://cutesoft.net/asp/EnableAll.asp
开发案例:DW版在线编辑器
指定子查询以测试行是否存在。
EXISTS subquery |
一个受限制的 SELECT 语句。
bit
如果子查询包含任何行,则返回 TRUE。
下面的示例针对 Employees 表中所列的每一名雇员,在 Orders 表中查找 Shipping Region 为“Washington”的所有订单。
复制代码 | |
---|---|
SELECT * FROM Orders WHERE ShipRegion = 'WA' AND EXISTS (SELECT EmployeeID FROM Employees AS Emp WHERE Emp.EmployeeID = Orders.EmployeeID) |
返回字符串中从右边开始指定个数的字符。
RIGHT ( character_expression , integer_expression ) |
兼容级别可能影响返回值。有关详细信息,请参阅 sp_dbcmptlevel (Transact-SQL)。
character_expression
字符或二进制数据表达式。character_expression 可以是常量、变量或列。character_expression 可以是任何能够隐式转换为 varchar 或 nvarchar 的数据类型,但 text 或 ntext 除外。否则,请使用 CAST 函数对 character_expression 进行显式转换。
integer_expression
正整数,指定 character_expression 将返回的字符数。如果 integer_expression 为负,则会返回错误。integer_expression 可以是 bigint 类型。
varchar 或 nvarchar
返回字符表达式、二进制表达式、文本表达式或图像表达式的一部分。有关可与该函数一起使用的有效 SQL Server 2005 数据类型的详细信息,请参阅数据类型 (Transact-SQL)。
SUBSTRING ( expression ,start , length ) |
必须以字符数指定使用 ntext、char 或 varchar 数据类型的偏移量(start 和 length)。必须以字节数指定使用 text、image、binary 或 varbinary 等数据类型的偏移量。
注意: |
---|
兼容级别可能影响返回值。有关兼容级别的详细信息,请参阅 sp_dbcmptlevel (Transact-SQL)。
|
expression
是字符串、二进制字符串、文本、图像、列或包含列的表达式。不要使用包含聚合函数的表达式。
start
指定子字符串开始位置的整数。start 可以为 bigint 类型。
length
一个正整数,指定要返回的 expression 的字符数或字节数。如果 length 为负,则会返回错误。length 可以是 bigint 类型。
注意: |
---|
因为 start 和 length 指定了字节数,所以对具有 DBCS 排序规则的 text 数据类型(如日本汉字)使用 SUBSTRING 时,可能会在结果的开始或结束位置导致字符拆分。此行为与 READTEXT 处理 DBCS 的方式一致。因此,我们建议您针对 DBCS 字符使用 ntext 而不是 text。我们建议的另一种备用方法是使用 varchar(max) 数据类型,因为它不会拆分 DBCS 排序规则的字符。
|
如果 expression 是受支持的字符数据类型,则返回字符数据。如果 expression 是受支持的 binary 数据类型,则返回二进制数据。
返回的字符串类型与指定表达式的类型相同(表中显示的除外)。
指定的表达式 | 返回类型 |
---|---|
char/varchar/text |
varchar |
nchar/nvarchar/ntext |
nvarchar |
binary/varbinary/image |
varbinary |
删除指定长度的字符,并在指定的起点处插入另一组字符。
STUFF ( character_expression , start , length ,character_expression ) |
如果结果值大于返回类型支持的最大值,则产生错误。
character_expression
一个字符数据表达式。character_expression 可以是常量、变量,也可以是字符列或二进制数据列。
start
一个整数值,指定删除和插入的开始位置。如果 start 或 length 为负,则返回空字符串。如果 start 比第一个 character_expression长,则返回空字符串。start 可以是 bigint 类型。
length
一个整数,指定要删除的字符数。如果 length 比第一个 character_expression长,则最多删除到最后一个 character_expression 中的最后一个字符。length 可以是 bigint 类型。
如果 character_expression 是受支持的字符数据类型,则返回字符数据。如果 character_expression 是一个受支持的 binary 数据类型,则返回二进制数据。