动态类型语言(以下简称:"动态语言"),在10年前就已流行起来。JavaScript更是成为了WEB前台开发的事实标准。但它们进入普通开发人员的视野也就在近几年。随着Web2.0和敏捷开发方法论的兴起,动态语言的灵活高效的特性成为了它被更多项目选择和使用的理由。一些大型网站已开始使用动态语言来实现,其中,国内比较优秀的作品有“豆瓣”。微软更是不甘落后,建立了DLR(动态语言运行时)来吸引动态语言爱好者在其上实现动态语言。IronPython就是其主要成员之一。

在本系列文章中,我们将逐步实现一个自定义控件,实现类似IDE的Immediate窗口的功能。用户可以在其中输入和运行IronPython代码。 【返回目录



先我们需要建立一个运行环境,并确保能够在其上运行Python脚本。大家可以从这里下载可运行的源代码。

我们首先来看一下运行结果:(提示:目前该程序是通过Ctrl+Enter执行你输入的代码。下面的输出窗口是IDE的Output窗口)

第一个版本运行效果图
点击看大图

其中主要的代码如下:

 1namespace DynamicLanguageConsole
 2{
 3    public partial class DLConsole : UserControl
 4    {
 5        public DLConsole()
 6        {
 7            InitializeComponent();
 8
 9            ScriptRuntimeSetup runtimeSetup = new ScriptRuntimeSetup(true);
10            this._runtime = ScriptRuntime.Create(runtimeSetup);
11            this._engine = this._runtime.GetEngine(typeof(PythonContext));
12            // 你亦可以使用下面的代码获得脚本引擎,但是,下面的方法可能会在未来版本被废弃
13            // this._engine = PythonEngine.CurrentEngine;
14            this._scope = this._engine.CreateScope();
15        }
 
16
17        ScriptRuntime _runtime;
18        ScriptEngine _engine;
19        ScriptScope _scope; 
20
21        public void Exec(string script)
22        {
23            _engine.CreateScriptSourceFromString(script, SourceCodeKind.Statements).Execute(_scope);
24        }
 
25    }

26}

程序中,我们保存了三个局部变量,ScriptRuntim,ScriptEngine和ScriptScope。

脚本运行时(ScriptRuntime):Hosting动态语言的入口。通过这个对象,你可以获得脚本引擎。添加全局变量等。
脚本引擎(ScriptEngine):实现语言特定的脚本功能,例如:编译源代码。
脚本空间(ScriptScope):提供了脚本运行的空间,脚本将会把其中定义的对象和变量等存储与这个空间里。.NET CLR对象也可以通过这个对象和脚本进行对象的共享。在《第三章:添加CLR对象到运行环境》中我们将会使用这个对象。

下面的图也许可以帮助你了解他们之间的关系。

High Level Hosting Object Relation
点击看大图

我们需要做的,就是构造这样三个对象(程序中的10-14行),然后,使用脚本引擎来编译用户输入的源代码,并且让该代码在ScriptScope上运行(程序中的23行)。

好了,仅仅需要这样7行代码,你的应用程序就具有了执行动态语言的能力。接下来,要让控制台控件更象一个标准的Python控制台《第二章:实现IConsole接口》。敬请关注feedsky

免责声明:本系列文章,完全是我个人研读IronPython源代码后找到的实现方案,并未详细的研究过IronPython的相关官方文档。因此,并不保证符合微软DLR和IronPython的设计思路,亦不能保证在DLR和IronPython 2.0正式发布后能够继续使用。

posted @ 2008-07-19 16:24 Colin Han 阅读(926) | 评论 (4)编辑

动态类型语言(以下简称:"动态语言"),应该说有很古老的历史了,10年前就已经在学术圈内流行起来。JavaScript更是成为了WEB前台开发的事实标准。但是他们进入普通开发人员的视野也就是在最近几年。随着Web 2.0和敏捷开发方法论的兴起。动态语言的灵活高效成为了他被大多数项目选择和使用的理由。一些大型的项目和网站都开始使用动态类型语言实现,其中,国内比较优秀的作品有“豆瓣”。各个大公司也纷纷加入其中。不断的推进着动态语言的发展。其中最典型的就是GooglePython语言的推崇。

最近Google推出了App Engine平台,为广大的开发人员提供了一个低成本,高扩展性的实现平台。关于App Engine的详细信息,后面我有时间的时候,考虑介绍一下。现在大家可以上网搜索一下。有很多详细的介绍。

推动动态语言发展的并不仅限于Google一家,IBM, Sun等公司也有相应的举措。微软,当然也不会落后,推出了他自己的动态语言平台——DLR 并且在其上实现了IronPython, IronRuby和JavaScript(其中,前两个应该算是社区作品,并且是开源的。最后一个是微软自己的实现,并且,目前还没有看到开源的说)。

目前我找不到DLR的源代码的独立下载地址,大家只能通过下载IronPython或IronRuby的源代码来获得DLR的源代码。简单来说,DLR就像.NET的CLR一样为动态语言提供了一套公共的运行时支持(例如:解释器,GC,语法树以及和CLR的交互等)。用微软官方的说法:DLR使动态语言开发者能够将精力放在该语言核心的功能上,而不是这些通用的功能。至少动态语言开发者并不再需要重写一套GC。虽然,很多开发人员总喜欢做这些。

微软的DLR使得动态语言开发者能够加少很多工作量,同样对于我们这些希望能够将动态语言嵌入到我们的应用程序中的开发人员也是一种好事。我们可以面向DLR去设计,提供基本的平台。然后,针对各种不同语言的特性进行一些优化,就可以简单的将他们嵌入到我们的运行环境里来。

随后的一系列文章中,我将制作一个自定义WinForm控件。该控件的功能就像一个控制台,通过将这个自定义控件嵌入你的窗口,使用户可以在其中输入代码并执行。大家可以将它想象为IDE中的Immediate窗口。

1. 建立运行环境并运行脚本
2. 实现IConsole接口,重定向输入输出
3. 添加CLR对象到运行环境
4. 使用扩展,使CLR对象对动态语言更友好

本系列中所有示例将基于IronPython 2.0 Beta 3.大家可以通过这里下载他的源代码

posted @ 2008-07-13 15:45 Colin Han 阅读(1558) | 评论 (4)编辑

1. 在WinForm上放置一个TabControl,并设置其Dock属性为Fill。

2. 在其中的一个Tab页上放置一个DateTimePicker控件

你会发现,当你在XP系统下,Resize Form时,DateTimePicker会闪烁。研究了很长时间,没有结果。最终放弃C#和Spy++,使用Google研究了一下 :-) 得出结论如下:

需要为DateTimePicker控件添加WS_EX_COMPOSITED Window Style.如下:

    public class MyDateTimePicker : DateTimePicker
    
{
        
protected override CreateParams CreateParams
        
{
            
get
            
{
                CreateParams ps 
= base.CreateParams;
                ps.ExStyle 
|= NativeMethods.WS_EX_COMPOSITED /*0x2000000*/;
                
return ps;
            }

        }

    }

这个Style仅仅被Window XP以上系统支持。功能是将Control的所有画法使用DoubleBuffer优化。(ControlStyles.OptimizedDoubleBuffer似乎仅对WM_PAINT优化,而DateTimePicker的闪烁是由WM_ERASEBKGND引起的)

做个记录,以便后人查询。

 

更新:(2008/01/03)
    注意,这个Style仅仅被Window XP以上操作系统接受,如果在Window 2000下运行添加了这个Style的DateTimePicker将会产生异常。

更新:(2008/02/03)
    注意,这个Style会导致DateTimePicker的DropDownButton没有按下效果。因此,不建议在项目中使用这个方案。关于更详细的解决方案,稍后我重新写一篇Blog。

posted @ 2007-12-29 14:46 Colin Han 阅读(264) | 评论 (0)编辑

 

在.NET 2.0中,微软对.NET 1.0中提出的WinForm的AutoScale能力进行了调整和增强。但是,微软始终没有跳出快速开发的圈子,因此,AutoScale做的并不彻底。其中有些工作还必须我们自己完成。

1. 什么是AutoScale?

我们知道,在不同的操作系统版本或语言版本之间,系统的默认字体是不同的。Window还提供了用户设置DPI的能力。因此,很多时候,我们在特定版本和DPI下设计的窗体,在另外一个操作系统下就会有一些字或图片被裁掉。如下图:

.NET提供了一套关于这个问题的解决方案。就是WinForm上的一组关于AutoScale的方法或属性。包括:

ContianerControl上有:

AutoScaleFactor property

AutoScaleDimensions property

CurrentAutoScaleDimensions property

AutoScaleMode property

PerformAutoScale method

Control上有:

Scale method

ScaleChildren method

GetScaledBounds method

一般情况下,微软会自动帮助你完成所有关于AutoScale的功能。你并不需要写特别的代码使用这些功能。

2.  AutoScale的实现细节

在DesignTime,系统会根据AutoScaleMode的设置不同,将一个参考值赋值给Form的AutoScaleDimensions属性。

例如:如果你选择AutoScaleMode为Font。DesignTime会自动为Form生成一行如下的代码来保存你设计时所使用的默认字体的宽和高:

this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 

Note: 当前系统为英文。因此,当前字体高度为13,宽度为6 

在运行时,CurrentAutoScaleDimensions属性会提取当前系统的相关设置。生成另外一个计算值。AutoScaleFactor属性表现了两个值的比值,作为下一步缩放的缩放因子。
比如,在日文系统下运行时,CurrenAutoScaleDimensions为(6f, 12f)。AutoScaleFactor为(1f, 0.9xxxf).

System.Win.Forms.ContainerControl会在OnLayout(还包括一堆其它的事件中)中对调用自己的 PerformAutoScale方法,其中对自己和它子孙调用Scale方法,并将AutoScaleFactor传入。从而实现调整他们的位置和大小,以适应当前操作系统的设置。

3. 使用AutoScale时需要注意的问题?

上面的实现应该说比较巧妙,加上Visual Studio的设计时支持。应该说已经可以完美的解决所有通过DesignTime设计的窗体或自定义控件。

但是,微软没有为这套系统进行完整的支持。如果你通过代码在运行时修改控件的位置或大小时,可以说你没有任何一个理想的方案来确保你的修改能够适应各种不同的操作系统设置。因为......当ContainerControl触发了PerformAutoScale方法后,为了确保下一次触发 PerformAutoScale方法不会累加操作,而将AutoScaleDimensions修改为和 CurrentAutoScaleDimensions一致。也就是说,你再也无法拿到设计时所使用的AutoScaleDimensions值。因此,你也就无法使用这套机制来确保你的修改操作可以兼容各种操作系统的设置。

在我们的产品中就有很多问题是这一点引起的。毕竟,在大多数产品中,并不会仅仅通过DesignTime托托拽拽就可以完成需求。因此,我们需要:

3.1 尽量使用DesignTime设置Control的Size和Location
3.2 如果不能使用DesignTime,自己需要维护AutoScaleDimensions值

看起来,我们只能自己手动生成我们自己的AutoScaleDimensions值。VS会将那一行代码生成在 InitializeComponents方法内部,该函数推出的时候,PerformAutoScale已经被调用,因此标准的 AutoScaleDimensions属性已经不能使用了。这里需要Hard Code。 // TODO: 谁有更好的建议?

并且在下列情况中手动对Control的Location或Size进行计算。

  • 修改Control的位置或大小时,手动计算正确的值。
  • 添加新Control到Controls之前,手动计算正确的Size和Location. 

我们需要使用前面我们自己维护的AutoScaleDimensions和当前容器的AutoScaleDimensions运算生成 AutoScaleFactor,然后自己计算新的位置和大小。这里,需要注意,不要参考Control的当前Size或Location。因为他们可能已经被Scale过一次了。

Note: 千万不要试图通过调用Control.Scale方法来完成计算。因为,ContainerControl的Scale方法会对所有子Control进行 Scale。但是,往往ContainerControl已经在它的构造函数中对它的子进行了Scale操作。结果相当于它的子进行了两次Scale。结果是错误的。

posted @ 2007-10-20 13:46 Colin Han 阅读(1828) | 评论 (2)编辑

 

以前,我们的开发人员和测试人员有时会发现一些类似下图的异常。

这些异常的发生往往都是看起来很随机,很难重现的。调用堆栈往往是空的。并且,当程序脱离IDE运行时,都不会发生这些异常。因此,我们经常认为这些异常是IDE的Bug导致。很少在意。(至少我以前是这样)

今天详细的看了一下MSDN中关于MDA的介绍。发现这些问题往往都是很重要的和潜在的问题。比如:PInvokeStackImbalance这个MDA能够帮助我们发现PInvoke的声明有问题。StreamWriterBufferedDataLost这个MDA可以帮助我们发现我们忘记调用StreamWriter.Close()方法。

因为很多MDA异常的触发都是在GC回收时进行的,因此表现比较随机。较难重现。

如果你希望自己控制监视哪些MDA异常,可以使用IDE中的Debug->Exceptions->Managing Debugging Assistants来选择捕获哪些MDA异常。如下图:

posted @ 2007-08-15 18:56 Colin Han 阅读(861) | 评论 (3)编辑
据说Asp.NET 2.0提供了用户管理的基本框架和实现。按照这个框架可以很容易的实现Web网站的用户管理功能。
呵呵,今天想学习一下。

遇到的第一个问题,就是如何建立Asp.NET用户管理数据库。好在微软提供了一个向导来帮助你完成这个工作。只需要在Visual Studio 2005 Command Line下输入“aspnet_regsql”即可以启动向导。上面的链接中有比较细致的介绍。

可惜,我并不想在我的机器上安装Sql Server .只想使用VS2005自带的Sql Express版。但是,上面的向导中并没有对Express版的支持。郁闷

呵呵,微软还是做事很细致的,他为我么提供了命令行的方式。虽然,实现确实很隐晦。不管怎样,下面的代码可以成功的将数据库建立起来。

建立数据库Type text here)...aspnet_regsql -C "Data Source=.\SQLEXPRESS;Integrated Security=True;User Instance=True" -d "数据库文件路径和全名.mdf" -A all

如果你还希望添加Session State的支持,只需要在后面加上“-ssadd”就可以了。
如果你希望从数据库里面清理掉用户管理的支持,只需要将上文中的"-A"改为"-R"即可。注意,这里区分大小写。
当然移除Session State的指令是"-ssremove"

关于更多的命令行参数,还是各位看官自己查MSDN或运行下面的命令行查看吧。
查看aspnet_regsql的命令行支持aspnet_regsql /?


posted @ 2007-07-29 14:20 Colin Han 阅读(694) | 评论 (2)编辑
呵呵,对Cnblogs关注的时间很长了,也搭建了自己的技术博客。但是,平心而论,对博客园的贡献还是很小了。

关于博客园的商业化,谈点自己的想法:
首先我想问的是:为什么博客园需要商业化?

对于这个问题,我觉得可能也只能有两种解释。
a. 博客园的生存受到了威胁,如果不进行商业化,可能就会死掉。
b. 有很多好的想法,好的服务,因为资金的原因无法实现。

如果不是这两个原因中的一个,我觉得这个问题就不需要讨论了。:-)

我想,对于这两个问题的解决方案是完全不同的。

a. 经济问题影响了博客园的生存。
我不知道Dudu老大是怎样维持博客园的正常运作的。仅仅靠首页上的广告吗?相信Dudu老大对博客园的贡献和他的辛苦是我们每个人都不能比拟的。相信相对于他的付出,他的收入是很微薄的。Dudu老大希望能够将他辛勤的结果转换为对自己相对好的的回报是很正常的想法。
如果博客园目前真的遇到了这个问题。我想,商业化中所最需要注意的问题是:“如何在商业化的过程中确保Dudu对博客园的掌握”。
因为,生存才是商业化的主要目的。我们不能也没有必要追求过高的回报率。只要能够维持正常的运作和生活就可以了。
而Dudu对博客园的完全控制,才能够保证将来进行第二轮商业化的过程时不会引入太多的复杂因素。
如果希望解决这个问题,我建议在博客园内部寻求资源。比如:提供一些收费的服务。或引入一些赞助机制等。因为我相信,博客园中的大多数人和Dudu的利益是一致的。而大多数企业和我们的利益并不总是一致。因此,我完全反对这个时候引入企业赞助。企业的赞助会影响博客园的中立性,会在将来影响博客园的发展或转型。
希望Dudu千万不要在商业化面前迷失了自己。

b. 没有足够的资源为大家提供更好的服务
最近两天对于博客园商业化的讨论非常多,但是,在其中我没有看到我们需要提供哪些新的服务为博客园的作者和读者带来更多的价值的内容。
如果真的有这样的服务,我想,通过在这些增值服务上进行收费可能是一个解决经济问题的方案。同样,如果我们能够找到很好的服务。寻找VC也就不会很困难了。

哈哈,说了这么多,把自己想说什么都给忘了。简单来说:
1. 不要为了生存而放弃博客园的精神。什么是博客园的精神呢?我想:“分享、简单、纯洁”应该是我心目中的博客园的精神。
2. 寻找杀手服务,找到它,博客园就可以发展壮大。否则,我觉得不商业化也罢。

呵呵,我是一个作技术的人。想法简单。某些说法可能也有些尖刻。只是希望博客园能够越来越好。能够成为每一个在这里安家的人的永远的家园。:-)

posted @ 2007-07-09 20:34 Colin Han 阅读(1637) | 评论 (9)编辑

昨日,与一同事一起在修一个多线程下使用我们的控件产品的Bug。现将相关的经验发布在这里。

1. 标准WinForm控件不支持多线程访问

这一点,其实是Windows的机制。.NET 中每一个Control其实都是一个Window,使用这些Window,原则上都应该在创建这个Window的线程中。否则,会产生异常。这一点,似乎Windows也没有强制约束。某些操作可能会扔异常,而有些情况下却不会。比如:访问这个Window的某些属性。

因此,.NET在Control上暴露了Invork方法,以实现将操作发送到Control所属的线程中执行。细节,可以参考我以前的一篇帖子

这一点,已经是标准做法。所以不能称之为Bug。

现在我们来看一下出现了什么Bug。用户的应用程序中,某些时候需要启动一个新的线程,在这个线程中构造并显示一个Form,其中包含我们的控件。当用户启动后,发现我们的产品不能够正确地显示。

什么原因呢?

2. 静态成员是元凶

根据经验,这种情况下的问题一般都出在静态成员上。我们在开发中,经常为了优化性能,而将一些对象缓存在静态成员中。如果我们将一个包含Window的对象缓存在静态对象中,对它的调用就可能会产生异常。

大家都知道,静态成员是属于整个AppDomain的,也就是说,所有的线程在共享同一个静态对象。当另外一个线程调用静态对象上的方法时,根据前面的规则(WinForm控件不支持多线程访问),异常产生了。

呵呵,这一点,是我在以前修Bug中的经验。但是,昨天似乎并不灵验。整个出现异常的部分没有发现缓存静态的Window对象。

经验告诉我,肯定是静态成员惹得祸。先看出问题的代码,发现这里缓存了一个静态的Bitmap。

难道是,这个Bitmap不允许跨线程访问?对这个Bitmap对象进行了锁(Lock)操作后,发现问题解决。于是得出了下面的经验。

3. 某些GDI对象也不允许跨线程访问

GDI对象(包括GDI+对象)都是有Handle的。可能在某些情况下,微软也不保证跨线程访问的可靠性。从昨天的调试结果来看,这些对象应该是不允许多个线程并发访问。这一点并没有太多的跟踪和调试,如果你有兴趣,可以尝试的再跟一下。

通过对这些对象加锁,避免并发访问,似乎问题已经解决。但是因为这一部分被使用的非常频繁(否则我们也不加Cache了),加锁后,发现对控件的性能产生很大的影响。看来仅仅加锁是不能解决所有问题的。

于是,昨天从Winking那里学了一着。

4. System.ThreadStaticAttribute

这个属性标示一个静态对象在每个线程中是独立的。因此,我们只要在这些缓存字段上加上这个属性。哈哈,问题解决。喔,看起来解决的太轻松了。先别急,现实往往比想象中残酷。

5. 静态对象的初始化的问题

我们一般会使用两种方式初始化静态对象。静态构造函数 和 第一次访问时。(我们经常会在静态对象的声明后面直接进行初始化,这种情况其实也是通过静态构造函数进行初始化的。只是编译器帮助我们将这些代码移动到了静态构造函数里面。因此,这里不单独讨论。)

如果我们将静态字段标记为线程唯一的,静态构造函数就不能够正确地初始化这个字段了。因为,静态构造函数只被调用一次。(它没有办法标记为线程唯一的:))

于是,这里就需要使用延迟构建模式。我们需要将这些静态成员声明为属性,在其Get函数中判断对象是否为空(或默认值,值类型)。从而确定是否需要构造缓存对象。 

6. 总结

呵呵,至此,所有的问题都解决了,Bug也已经修复。总体来说,静态对象始终是一个不安全因素。在目前我负责的项目中,我们是尽量避免使用静态成员。如果需要缓存对象,我们也会将这些缓存对象放在一个特定的池中。确保缓存对象是面向特定实例的而不是全局的。避免出现上面的问题。

相关文章:.NET下跨线程访问Control。

posted @ 2007-03-21 13:30 Colin Han 阅读(3223) | 评论 (4)编辑

一般情况下,安装VS 2005时,安装程序会自动配置本地IIS服务使用ASP.NET 2.0。我们可以直接在VS 2005下编写或调试WEB应用程序。

但是,如果我们先安装了VS2005,然后才安装的IIS。这时,IIS会设置为使用ASP.NET 1.0。我们在VS2005中建立WEB程序是会出现下面的提示:

The site 'http://localhost/xxxxxx' has not been configured for use with ASP.NET 2.0. Microsoft Visual Studio has been designed for use with ASP.NET 2.0; if not configured some features may make incorrect assumptions, and pages designed with the tool may not render correctly.

并且不能自动配置成功。

这时,只需要在Visual Studio 2005 Command Prompt中执行下面的命令

aspnet_regiis -i -enable

posted @ 2007-03-03 13:41 Colin Han 阅读(1469) | 评论 (1)编辑

 今天发现微软已经将.NET Framework 3.0添加到Windows Update中了。但是至少目前还没有放在自动更新中。

posted @ 2007-02-01 13:20 Colin Han 阅读(174) | 评论 (1)编辑
在反编译微软的代码后,发现下面的代码:
1 internal static int GetCombinedHashCodes(params int[] args)
2 {
3     int num1 -757577119;
4     for (int num2 = 0; num2 < args.Length; num2++)
5     {
6         num1 = (args[num2] ^ num1) * -1640531535;
7     }
8     return num1;
9 }
这个方法在System.Windows.Forms.WindowsFormsUtils中。

实在很想知道,其中的两个魔法数字有什么特别的,或者只是某人心情好?

posted @ 2006-11-16 19:34 Colin Han 阅读(219) | 评论 (0)编辑
收藏一下,分享一下。
不多说了,自己看吧。:-)

Jensen Harris: An Office User Interface Blog : The Office 2007 UI Bible

powered by performancing firefox

posted @ 2006-11-15 13:41 Colin Han 阅读(289) | 评论 (0)编辑
因为工作需要,写了个简单的测试程序测试了一下List<T>, LinkedList<T>, Dictionary<TKey, TValue>, SortedList<TKey, TValue>的性能。

测试结果中有两点出乎意料:
1. LinkedList的内存占用很大,比List大了将近60%。
    我没有细看为什么多出这么多内存占用。但是如果用我自己写的一个单链表,内存占用比List低。因为工作重点不在这里,我也不打算细究为什么了。但是感觉上,LinkedList的优势应该在小数据量,频繁添加删除的场景下。

2. SortedList的访问性能比Dictionary低。
    一般认为向SortedList中添加节点的性能会比较低,因为它需要维护一个有序表,存在性能开销(当数据有序时,添加节点的开销大约是Dictionary的170%)。但是,事实上,对SortedList中节点的读写性能也要低于Dictionary(近7倍的开销)。这一点我觉得比较难以理解。

附件中是这次测试使用的程序,有兴趣的你,也许可以下载后试验一下,看看为什么是这样?

附件:http://www.cnblogs.com/Files/Cajon/TestListPerformance.zip

powered by performancing firefox

posted @ 2006-08-27 15:55 Colin Han 阅读(6619) | 评论 (0)编辑
再次测试向关于博客园的TrackBack功能进行TrackBack
posted @ 2006-08-16 11:31 Colin Han 阅读(111) | 评论 (0)编辑
看到idiorEnterLib ObjectBuild vs Castle WindsorContainer, part 1中的评论,发表点自己的看法,同时测试一下博客园的TraceBack。

"解耦"应该是基于接口依赖而进行的,也就是说,所有的契约都在接口中定义了。耦合的双方都应该不知道对方是什么,只知道对方符合某个契约。
从这一点来说,配置文件和属性都可以实现解耦的目的。

另一方面来说,我们为什么要解耦?
一、降低复杂度
二、提高柔性

实现这两个目标,应该说封装变化是一个重要的途径。于是,我们需要将变化和复杂的耦合关系封装起来。从这一方面来说,配置文件应该说是优于属性的。因为配置文件将复杂度和变化全部集中在了一个点上(配置文件上)。因此最大化了解耦的价值。而属性,依然将复杂度分散在系统内部的很多点上,因此没有达到最大化解耦的价值。
posted @ 2006-08-15 18:35 Colin Han 阅读(110) | 评论 (0)编辑
一篇不错的文章,介绍了.NET开发中性能的方方面面。看起来也是翻译过来的,翻译的确实不太好 *_*! 但是值得学习和参考。

首页:
http://pingce.zhongsou.com/SoftChannel/72342380484755456/20030828/1724489.shtml

关于JIT优化的章节,可以直接看其中的第四页。其中介绍了JIT在什么时候会将一个函数内联编译,从而降低方法调用的开销。


powered by performancing firefox

posted @ 2006-08-07 15:36 Colin Han 阅读(234) | 评论 (0)编辑
在.NET中,一个Control是属于一个特定的线程的。如果要在另外一个线程中访问这个Control的Handler(其实,Control的很多属性都会访问到Control的Handler)。.NET 或 操作系统会抛出一个异常。

但是,某些时候我们必须这样使用。微软已经在.NET Framework中为我们包装好了方法,供我们使用:
public Object Control.Invoke (
Delegate method,
params Object[] args
)

Visual Basic (Declaration)

Public ReadOnly Property InvokeRequired As Boolean


Visual Basic (Usage)

Dim instance As Control Dim value As Boolean  value = instance.InvokeRequired 


public bool Control.InvokeRequired { get; }

通过InvokeRequired属性,我们可以判断特定的Control是否属于当前线程。如果该属性返回真,我们就必须使用Control.Invoke方法,将访问逻辑发送到Control所属的线程里运行。


powered by performancing firefox

posted @ 2006-06-23 13:00 Colin Han 阅读(952) | 评论 (1)编辑
微软即将启动新的邮件帐户域名,@live.com 和 @windowslive.com。具微软Windows Live Mail的Blog说,将会在这个月的20号开发申请。并且有准备提供从老的@hotmail.com和@msn.com迁移到新帐号的能力。

关注一下。

消息源:WindowsLiveMail Support: Coming Soon: @live.com and @windowslive.com domains

powered by performancing firefox

posted @ 2006-06-14 15:21 Colin Han 阅读(1137) | 评论 (0)编辑
使用Firefox,默认的使用Google.com作为搜索引擎。但是最近一段时间,使用Google.com搜索常有失败。只好退而求其次,使用被阉割的Google.CN
但是,不能使用工具栏上的搜索,总是很不方便。使用Firefox的添加搜索引擎页面上也没有Google.cn。只好自己研究解决。下面是解决办法:

首先找到Firefox的安装路径,一般情况下为:C:\Program Files\Mozilla Firefox。其中包含子目录:searchplugins。其中包含文件google.src。
新建一个新的文件,命名为:google-cn.src,同时,复制google.gif为google-cn.gif。打开google-cn.src编辑。内容如下:

--------------------------------------------------------------------------------------------
# Mozilla/Google plug-in by amitp+mozilla@google.com

<search
   name="Google.CN"
   description="Google.CN Search"
   method="GET"
   action="http://www.google.cn/search"
   queryCharset="utf-8"
>

<input name="q" user>
<inputnext name="start" factor="10">
<inputprev>
<input name="ie" value="utf-8">
<input name="oe" value="utf-8">

<interpret
    browserResultType="result"
    charset = "UTF-8"
    resultListStart="<!--a-->"
    resultListEnd="<!--z-->"
    resultItemStart="<!--m-->"
    resultItemEnd="<!--n-->"
>
</search>

<browser
    update="https://addons.mozilla.org/searchplugins/updates/googlecn.src"
    updateIcon="https://addons.mozilla.org/searchplugins/updates/googlecn.gif"
    updateCheckDays="1"
>

--------------------------------------------------------------------------------------------

修改部分,我用粗体标注了。保存后,重新打开Firefox。在Firefox的搜索引擎列表中会多出一个Google.CN。以后就可以使用Google.CN进行搜索了。
posted @ 2006-06-02 22:03 Colin Han 阅读(297) | 评论 (1)编辑
刚刚新买了64位的新机器,匆匆装上一个64位的XP,体验一下新机器的感觉。
结果一路问题多多。先是安装盘不能自启动。不知道微软在做什么?VLP版DVD中包含多个版本的XP,但是,只有32位的可以自启动安装,64位版需要先将iso文件刻成光盘,然后安装 晕,好在我先看了说明文件。)

然后,是UltraEdit和WinRAR不能正常的注册右键菜单,Windows流氓软件清理大师无法正常工作

接着是VS2005的序列号没有自动填入,不知道为什么。印象中在32位机器上安装的时候是自动填好的。  

最郁闷的是:使用VS2005新建一个工程,连接到一个Access 2003建的数据库。运行时,在Fill数据时直接产生Microsoft.Jet.OLEDB.4.0数据库提供程序没有注册的错误。

InvalidOperationException
The 'Microsoft.Jet.OLEDB.4.0' provider is not registered on the local machine.

经多方检查,似乎数据引擎已经注册良好。四处打听也没有什么结果。那个郁闷…………

最后,通过一些官方途径,才了解到,原来这个是微软JET数据引擎的兼容性问题。解决方法,只能是让程序编译成32位版运行。

修改方法:
    打开项目配置管理器(Configuration Manager),将项目的运行平台(Platform)修改为x86。如下图:



重新编译,运行。
posted @ 2006-05-30 20:46 Colin Han 阅读(1487) | 评论 (1)编辑
这几天在试用Performancing写Blog。yicone要求我写一下怎么配置Performancing

首先,你要进入你的Blog的[选项/Configurate]页面。在页面最下面,Dudu已经为我们提供了MetaWeblog的API支持,如下图:

记住上面黄色的地址。

OK,现在你可以下载Performancing并安装它了。当然,你还需要Firefox

安装之后,会发现在Firefox的右下角多处一个图标,点击,可以打开Performancing写作面板。面板的右面是配置你的Blog的地方,如下图:

点击添加,可以开始配置你的Blog了。首先输入你的Blog地址(例如,我的地址:http://cajon.cnblogs.com)如下图:

下一步,Performancing会检查Blog是否存在。检查完成后,如下图:

继续下一步,选择Blog的类型,这一定要选择Custom Blog。如下图:

继续,选择Blog API类型——MateWeblog API。填入前面记下的地址。如下:

继续,输入你在博客园的用户名和密码。配置完成~~~~~~~

你会发现,列表里多处一条,就是你新加入的Blog。以后,你就可以使用Performancing来书写Blog了。

哈哈,就到这里,如果你有什么问题。可以在下面留言。尽我所能给你帮助吧。
posted @ 2006-05-16 13:45 Colin Han 阅读(427) | 评论 (2)编辑
今天看到一篇Blog,将来我们可以用Office 2007写Blog。

点击图片,查看大图。

可以直接将一篇Word文档发布到你的Blog上。目前看来,支持的Blog平台还不太多。以微软的做事方式,应该会暴露接口,提供第三方开发的能力。



消息源:Joe Friend: Microsoft Office Word : Blogging from Word 2007

Technorati Tags: ,

powered by performancing firefox

posted @ 2006-05-13 13:34 Colin Han 阅读(136) | 评论 (0)编辑
今天开始试用Firefox,听说他的插件很多,就装了一个,用了一下感觉真的很不错。呵呵,让人兴奋的是,刚刚装了一个插件Performancing,可以离线写Blog。

很激动,我的两个Blog(博客园MSN Spaces)都支持。据说支持的Blog平台也很广。感觉很不错。

现在就试用一下,感觉美中不足的是它的Editor不支持CuteEditor的代码着色的功能。

试试先..............

Note: Performancing的右边栏中有一项“Notes”。千万不要乱点。否则你辛辛苦苦写的东西都回不翼而飞的。并且不支持Undo。郁闷,我就被害一次。

好了,要回家了。老婆要不高兴了...一高兴,又忘了回家了。
posted @ 2006-04-25 18:35 Colin Han 阅读(283) | 评论 (3)编辑
前几天在Channel9上得到了别人的邀请,可以试用微软新的IM系统——Windows Live™ Messenger,MSN Messenger的升级版。
现在,我有几个邀请可以送出。如果有人想要,可以在下面跟贴,留下你们的Hotmail或MSN邮箱地址。
posted @ 2006-04-11 15:45 Colin Han 阅读(267) | 评论 (14)编辑