MobiNav

All Things Mobility

février 12th, 2007

FrameWork

[source: 中科永联高级技术培训中心

框架(Framework)是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法;另一种定义认为,框架是可被应用开发者定制的应用骨架。前者是从应用方面而后者是从目的方面给出的定义。

      可以说,一个框架是一个可复用的设计构件,它规定了应用的体系结构,阐明了整个设计、协作构件之间的依赖关系、责任分配和控制流程,表现为一组抽象类以及其实例之间协作的方法,它为构件复用提供了上下文(Context)关系。因此构件库的大规模重用也需要框架。

      构件领域框架方法在很大程度上借鉴了硬件技术发展的成就,它是构件技术、软件体系结构研究和应用软件开发三者发展结合的产物。在很多情况下,框架通常以构件库的形式出现,但构件库只是框架的一个重要部分。框架的关键还在于框架内对象间的交互模式和控制流模式。

      框架比构件可定制性强。在某种程度上,将构件和框架看成两个不同但彼此协作的技术或许更好。框架为构件提供重用的环境,为构件处理错误、交换数据及激活操作提供了标准的方法。

      应用框架的概念也很简单。它并不是包含构件应用程序的小片程序,而是实现了某应用领域通用完备功能(除去特殊应用的部分)的底层服务。使用这种框架的编程人员可以在一个通用功能已经实现的基础上开始具体的系统开发。框架提供了所有应用期望的默认行为的类集合。具体的应用通过重写子类(该子类属于框架的默认行为)或组装对象来支持应用专用的行为。

      应用框架强调的是软件的设计重用性和系统的可扩充性,以缩短大型应用软件系统的开发周期,提高开发质量。与传统的基于类库的面向对象重用技术比较,应用框架更注重于面向专业领域的软件重用。应用框架具有领域相关性,构件根据框架进行复合而生成可运行的系统。框架的粒度越大,其中包含的领域知识就更加完整。
      框架,即framework。其实就是某种应用的半成品,就是一组组件,供你选用完成你自己的系统。简单说就是使用别人搭好的舞台,你来做表演。而且,框架一般是成熟的,不断升级的软件。

      框架的概念最早起源于Smalltalk环境,其中最著名的框架是Smalltalk 80的用户界面框架MVC(Model-View-Controller)。随着用户界面框架Interviews [Linton 89]和ET++ [Weinand 89] 的开发和发布,框架研究越来越受到研究人员的重视。虽然框架研究最初起源于用户界面领域,但它还被成功地应用到其他领域中,如操作系统 [Russo 90]、火警系统 [Molin 96a,Molin 96b] 等。Taligent公司于1992年成立后,框架研究受到了广泛的重视。该公司计划基于框架来开发一个完整的面向对象操作系统。另外,该公司还发布了一套支持快速应用开发的工具集CommonPoint,其中包括了上百个面向对象框架 [Andert 94,Cotter 95]。
框架目前还没有统一的定义,其中Ralph Johnson所给出的定义基本上为大多数研究人员所接受:

      一个框架是一个可复用设计,它是由一组抽象类及其实例间协作关系来表达的 [Johnson 98]。

      这个定义是从框架内涵的角度来定义框架的,当然也可以从框架用途的角度来给出框架的定义:

      一个框架是在一个给定的问题领域内,一个应用程序的一部分设计与实现[Bosch 97]。

      从以上两个定义可以看出,框架是对特定应用领域中的应用系统的部分设计和实现,它定义了一类应用系统(或子系统)的整体结构。框架将应用系统划分为类和对象,定义类和对象的责任,类和对象如何互相协作,以及对象之间的控制线程。这些共有的设计因素由框架预先定义,应用开发人员只须关注于特定的应用系统特有部分。框架刻画了其应用领域所共有的设计决策,所以说框架着重于设计复用,尽管框架中可能包含用某种程序设计语言实现的具体类。
 
      一个基于框架开发的应用系统包含一个或多个框架,与框架相关的构件类,以及与应用系统相关的功能扩展。与应用系统相关的扩展包括与应用系统相关的类和对象。应用系统可能仅仅复用了面向对象框架的一部分,或者说,它可能需要对框架进行一些适应性修改,以满足系统需求。

      面向对象的框架作为一种可复用的软件,在基于框架的软件开发过程中会涉及到框架的开发和利用两个方面的工作。框架的开发阶段在于产生领域中可复用的设计。该阶段的主要结果是框架以及与框架相关的构件类。该阶段的一个重要活动是框架的演变和维护。象所有软件一样,框架也易于变化。产生变化的原因很多,如应用出错,业务领域变化,等等。

      不论是哪一种技术,最终都是为业务发展而服务的。从业务的角度来讲。首先,框架的是为了企业的业务发展和战略规划而服务的,他服从于企业的愿景(vision);其次,框架最重要的目标是提高企业的竞争能力,包括降低成本、提高质量、改善客户满意程度,控制进度等方面。最后,框架实现这一目标的方式是进行有效的知识积累。软件开发是一种知识活动,因此知识的聚集和积累是至关重要的。框架能够采用一种结构化的方式对某个特定的业务领域进行描述,也就是将这个领域相关的技术以代码、文档、模型等方式固化下来。

一、框架要解决的问题

      框架要解决的最重要的一个问题是技术整合的问题,在J2EE的框架中,有着各种各样的技术,不同的软件企业需要从J2EE中选择不同的技术,这就使得软件企业最终的应用依赖于这些技术,技术自身的复杂性和技术的风险性将会直接对应用造成冲击。而应用是软件企业的核心,是竞争力的关键所在,因此应该将应用自身的设计和具体的实现技术解耦。这样,软件企业的研发将集中在应用的设计上,而不是具体的技术实现,技术实现是应用的底层支撑,它不应该直接对应用产生影响。

      要理解这一点,我们来举一些例子:

      一个做视频流应用的软件企业,他为电广行业提供整体的解决方案。他的优势在于将各种各样的视频硬件、服务器、和管理结合起来,因此他扮演的是一个集成商的角色。因此他的核心价值在于使用软件技术将不同的硬件整合起来,并在硬件的整合层面上提供一个统一的管理平台。所以他的精力应该放在解决两个问题:

      如何找到一种方法,将不同的硬件整合起来,注意,这里的整合并不是技术整合,而是一种思路上的整合。首先要考虑的绝对不是要使用什么技术,而是这些硬件需要提供哪些服务,需要以什么样的方式进行管理。因此,这时候做的事情实际上是对领域进行建模。例如,我们定义任何一种硬件都需要提供两种能力,一种是统一的管理接口,用于对所有硬件统一管理;另一种是服务接口,系统平台可以查询硬件所能够提供的服务,并调用这些服务。所以,设计的规范将会针对两种能力进行。

      另一个问题是如何描述这个管理系统的规范。你需要描述各种管理活动,以及管理中所涉及的不同实体。因为管理系统是针对硬件的管理,所以它是构架在硬件整合平台之上的。

      在完成业务层面的设计之后,我们再来看看具体的技术实现。光有规范和设计是不够的,我们还需要选择一个优秀的技术。由于是对不同硬件的整合,我们想到采用Java提供的JMX技术。JMX技术适合用来进行系统整合,它定义了一个通用的规范,并给出了远程管理端口的一些默认实现。JMX已经经过了实践的检验,不少的应用服务器都采用了以JMX为基础的结构,例如有名的JBoss。JMX已经是一个很好的开始了,但是我们还需要在JMX的基础上再做一些工作。

二、什么要用框架?

      因为软件系统发展到今天已经很复杂了,特别是服务器端软件,设计到的知识,内容,问题太多。在某些方面使用别人成熟的框架,就相当于让别人帮你完成一些基础工作,你只需要集中精力完成系统的业务逻辑设计。而且框架一般是成熟,稳健的,他可以处理系统很多细节问题,比如,事物处理,安全性,数据流控制等问题。还有框架一般都经过很多人使用,所以结构很好,所以扩展性也很好,而且它是不断升级的,你可以直接享受别人升级代码带来的好处。

      框架一般处在低层应用平台(如J2EE)和高层业务逻辑之间的中间层。

      软件为什么要分层?
      为了实现“高内聚、低耦合”。把问题划分开来各个解决,易于控制,易于延展,易于分配资源…总之好处很多啦:)。

三、为什么要进行框架开发?

      框架的最大好处就是重用。面向对象系统获得的最大的复用方式就是框架,一个大的应用系统往往可能由多层互相协作的框架组成。

      由于框架能重用代码,因此从一已有构件库中建立应用变得非常容易,因为构件都采用框架统一定义的接口,从而使构件间的通信简单。

      框架能重用设计。它提供可重用的抽象算法及高层设计,并能将大系统分解成更小的构件,而且能描述构件间的内部接口。这些标准接口使在已有的构件基础上通过组装建立各种各样的系统成为可能。只要符合接口定义,新的构件就能插入框架中,构件设计者就能重用构架的设计。

      框架还能重用分析。所有的人员若按照框架的思想来分析事务,那么就能将它划分为同样的构件,采用相似的解决方法,从而使采用同一框架的分析人员之间能进行沟通。

      采用框架技术进行软件开发的主要特点包括:
领域内的软件结构一致性好;

建立更加开放的系统;

重用代码大大增加,软件生产效率和质量也得到了提高;

软件设计人员要专注于对领域的了解,使需求分析更充分;

存储了经验,可以让那些经验丰富的人员去设计框架和领域构件,而不必限于低层编程;

允许采用快速原型技术;

有利于在一个项目内多人协同工作;

      大粒度的重用使得平均开发费用降低,开发速度加快,开发人员减少,维护费用降低,而参数化框架使得适应性、灵活性增强。

四、与框架相关的概念

1. 白盒与黑盒框架

      框架可分为白盒(White-Box)与黑盒(Black-Box)两种框架。

      基于继承的框架被称为白盒框架。所谓白盒即具备可视性,被继承的父类的内部实现细节对子类而言都是可知的。利用白盒框架的应用开发者通过衍生子类或重写父类的成员方法来开发系统。子类的实现很大程度上依赖于父类的实现,这种依赖性限制了重用的灵活性和完全性。但解决这种局限性的方法可以是只继承抽象父类,因为抽象类基本上不提供具体的实现。白盒框架是一个程序骨架,而用户衍生出的子类是这个骨架上的附属品。

      基于对象构件组装的框架就是黑盒框架。应用开发者通过整理、组装对象来获得系统的实现。用户只须了解构件的外部接口,无须了解内部的具体实现。另外,组装比继承更为灵活,它能动态地改变,继承只是一个静态编译时的概念。

      在理想情况下,任何所需的功能都可通过组装已有的构件得到,事实上可获得的构件远远不能满足需求,有时通过继承获得新的构件比利用已有构件组装新构件更容易,因此白盒和黑盒将同时应用于系统的开发中。不过白盒框架趋向于向黑盒框架发展,黑盒框架也是系统开发希望达到的理想目标。

2. 热点、食谱以及好莱坞原则

      成功的框架开发需要确定领域专用的“热点” (Hot spot)。应用开发者在框架的基础上进行开发,只须扩展框架的某些部分,“热点”就是在应用领域的一种扩展槽,开发者根据自己的需要填充这些扩展槽。“热点”使框架具有灵活性,如在具体的实现中,扩展槽可以被看成是一些抽象类,开发者通过重写抽象方法获得具体实现。

      “食谱” (Cookbook)就是描述如何使用框架方法的文档。在“食谱”中包含了许多“烹饪”方法,这些“烹饪”方法相当于一些具体的操作步骤,描述了为解决某一专门问题如何使用框架的详细方法。框架的内部设计和实现细节通常不出现在“食谱”中。

      框架的一个重要特征就是用户定义的方法经常被框架自身调用,而不是从用户的应用代码中调用。这种机制常称为“好莱坞原则”(Hollywood Principle)或“别调用我们,我们会调用您”。
五、常见的JAVA框架有什么?

WAF:
全称:WEB APPLICATION FRAMEWORK
主要应用方面:EJB层,(WEB层也有,但是比较弱)。
主要应用技术:EJB等
出处:java.sun.com
简述:这是SUN在展示J2EE平台时所用的例子PetStore(宠物商店系统)里面的框架。是SUN蓝皮书例子程序中提出的应用框架。它实现了 MVC和其他良好的设计模式。SUN的网站上有技术资料,最好下载PetStore来研究,WEBLOGIC里自带此系统,源码在bea\weblogic700\samples\server\src\petstore。这是学习了解J2EE的首选框架。
免费。

Struts:
主要应用方面:WEB层。
主要应用技术:JSP,TagLib,JavaBean,XML等
出处:http://jakarta.apache.org/struts/index.html
简述:这是APACHE的开源项目,目前应用很广泛。基于MVC模式,结构很好,基于JSP。Jbuilder8里已经集成了STRUTS1.02的制作。
免费。

简述WAF+STRUTS结合的例子:WEB层用STRUTS,EJB层用WAF:
JSP(TagLib)——>ActionForm——>Action  ——>
  Event——>EJBAction——>EJB    ——>DAO——>Database 
JSP(TagLib) (forward) < ——Action  <——EventResponse<——                

Turbine:
主要应用方面:WEB层。
主要应用技术:servlet等
出处:jakarta.apache.org
简述:这是APACHE的开源项目。基于SERVLET。据说速度比较快,基于service(pluggable implementation可插拔的执行组件)的方式提供各种服务。
免费。

COCOON:
主要应用方面:WEB层。
主要应用技术:XML,XSP,servlet等
出处:
http://cocoon.apache.org/2.0/
简述:这是APACHE的一个开源项目。基于XML,基于XSP(通俗地说,XSP是在XML静态文档中加入Java程序段后形成的动态XML文档。)。特点是可以与多种数据源交互,包括文件系统,数据库,LDAP,XML资源库,网络数据源等。
免费。

主要应用方面:WEB层。
主要应用技术:servlet等
出处:http://www.nextapp.com/products/echo/
简述:nextapp公司的一个开源项目。基于SERVLET。页面可以做的很漂亮,结合echopoint,可以作出很多图形效果(里面用了jfreechart包)。使用SWING的思想来作网页,把HTML当作JAVA的类来做。但是大量使用Session,页面分帧(Frame)很多,系统资源消耗很大。
免费。  

JATO:
全称:SUN ONE Application Framework
主要应用方面:WEB层。
主要应用技术:JSP,TagLib,JavaBean等
出处:http://www.sun.com/
简述:这是SUN推出的一个商业性框架,一看名字就知道是结合SUN ONE的平台推出的。我下载了JATO2.0看了一下,感觉有些简单,使用了JSP+TagLib+JavaBean。如他的DOC所说JATO是适合用在小的WEB应用里。
免费。

TCF:
全称:Thin-Client Framework
主要应用方面:JAVA GUI。
主要应用技术:JAVA application等
出处:http://www.alphaworks.ibm.com/tech/tcf
简述:这是IBM出的一个框架。基于MVC模式,基于JAVA Application。推荐一篇介绍文章:java/j-tcf1/index.shtml »>http://www-900.ibm.com/developerWorks/cn/java/j-tcf1/index.shtml
收费:每个企业对象license:2000美元。

oof-Wm — un framework multiplateforme pour la creation de Window Manager, open-source écrit en C++ (Homepage GoogleProject)
Apache Cocoon — un environnement servlet de développement JAVA/XML pour le web, fondation Apache Software
Apache Struts — de la fondation Apache Software
Catalyst (logiciel) — un framework web open-source écrit en langage de programmation Perl
Cocoa — de la société Apple
Django — un framework web open-source écrit en langage de programmation Python
Dojo — développement rapide d’applications en Javascript exécutées côté butineur et communiquant avec le serveur avec une granularité inférieure à la page grâce à Ajax.
Eclipse — open-source de la fondation Eclipse Foundation Software
EVAcms — de la société EVA Soluções
NetBeans — de la société Sun Microsystems
Lampshade (Framework) — de la société Think Computer
Microsoft .NET — de la société Microsoft
Maypole framework — un framework web open-source écrit en Perl
MIReG – Framework de métadonnées de l’Union européenne
RIFE — un framework web open-source écrit en langage de programmation Java
Ruby on Rails — un framework web open-source écrit en langage de programmation Ruby
Seaside — un framework web open-source écrit en Smalltalk
TurboGears — un framework web open-source écrit en langage de programmation Python
Zope — un framework web open-source écrit en langage de programmation Python
XNA — un framework de jeu vidéo écrit en C#. Il permet le développement d’application pour plateformes Xbox 360 & PC

février 2nd, 2007

HttpLite of Wince

[Source : msdn blogs

Windows CE since CE 2.12 has had Wininet.dll ported from the desktop.  It’s cool since it’s pretty nearly the same as what you get on Windows XP and lets us have stuff like Internet Explorer.  It’s not cool for headless devices, where it won’t run and would chew up a lot of ROM+RAM even if it did.

In CE 4.0, we brought the tiny wininet that we had in CE 2.11 out of retirement and rechristened it httplite.dll.  Httplite was made to run inside a headless device and provide about %80 of the key functionality that Wininet does.  It’s about 65KB of ROM on an x86 build, to get an idea of its size.  Both Wininet and httplite are perfectly safe to run inside servers (like web server) on CE, unlike the wininet on the desktop where I think there are gotchas.

To get an image with httplite in it, add « set __SYSGEN_HTTPLITE=1″ and optionally (to get FTP related functionality) « set __SYSGEN_HTTPLITE_FTP=1″ to your CEBase.bat.

To build apps using wininet, you need to #include .  It’s a lot like wininet.h, except dubinet.h only has definitions for stuff httplite.dll supports.  Use it so that if you try to use some wininet construct httplite does not support, you’ll get a compile time error that’s easy to debug rather than some weird run-time error down the road.  Link to httplite.lib, and then you’re ready to start using httplite!

Note 1: Httplite is for OEMs (platform builders) only and is not something ISV’s can add to existing images.  If you’re an ISV and you want this, talk with your OEM about having them add it to your platform.

Note 2: Httplite is untested and undocumented.  It gets a lot of use by Microsoft components that run on headless devices and use it (UPnP in particular), but this isn’t quite the same as extensive API level testing.  I also know of at least one customer via newsgroups who has used it with great success.  If you find bugs Microsoft would like to know, but we cannot promise to fix them or help you debug anything.

Note 3: Httplite is is CE 4.0-5.0.  There are no plans to cut it from future releases, but if we can get wininet.dll smaller and running on headless devices then httplite will be retired again.

sources:

HttpLite from NRAO

février 2nd, 2007

HTTP comment ça marche?

look here for an overview. and RFC 1945 for details.

octobre 27th, 2006

在C#程序中实现插件架构

 [source: 51cto] 

在.NET框架下的C#语言,和其他。NET语言一样提供了很多强大的特性和机制。其中一些是全新的,而有些则是从以前的语言和平台上照搬过来的。然而,这种巧妙的结合产生了一些有趣的方法可以用来解决我们的问题。这篇文章将讲述如何利用这些奇妙的特性,用插件(plug-ins)机制建立可扩展的解决方案。后面也将提供一个简要的例子,你甚至可以用这个东西来替换那些已经在很多系统中广泛使用的独立的程序。在一个系统中,可能有很多程序经常需要进行数据处理。可能其中有一个程序用于处理雇员的信息,而另一个用来管理客户关系。

在大多数情况下,系统总是被设计为很多个独立的程序,他们之间很少有交互,经常使用复制代码的办法来共享。而实际上这样的情况可以把那些程序设计为插件,再用一个单一的程序来管理这些插件。这种设计可以让我们更好的在不同的解决方案中共享公用的方法,提供统一的感观。

图片一是一个例子程序的截图。用户界面和其他常见的程序没有什么不同。整个窗体被垂直的分割为两块。左边的窗格是个树形菜单,用于显示插件列表,在每个插件的分支下面,列出了这个插件所管理的数据。而右边的窗格则用于编辑左边被选中的插件的数据。各个插件提供各自的编辑数据的界面。图片一展示了一个精巧的工作区。

开始

那么,主程序必须能够加载插件,然后和这些插件进行通信,这样才能实现我们的设计.所有这些的实现可以有很多不同的方法,仅取决于开发者选择的语言和平台.如果选择的是C#和.NET,那么反射(reflection)机制可以用来加载插件,并且其接口和抽象类可以用于和插件通信.

为了更好的理解主程序和插件之间的通信,可以先了解一下设计模式.设计模式最早由Erich Gamma提出1,它利用架构和对象思想来实现通用的通信模型.不管组件是否具有不同的输入和输出,只要他们有相似的结构.设计模式可以帮助开发者利用广受证明的面向对象理论来解决问题.事实上它就是描述解决方案的语言,而不用管问题的具体细节或者编程语言的细节.设计模式策略的关键点在于如何把整个解决方案根据功能来分解,这种分解是通过把主程序的不同功能分开执行而完成的.这样主程序和子程序之间的通信可以通过设计良好的接口来完成.通过这种分解我们立即可以得到这两个好处:第一,软件项目被分成较小的不相干的单位,工作流程的设计可以更容易,而较小的代码片断意味着代码更容易建立和维护.第二个好处在于改变程序行为的时候并不会关系到主程序的运行,主程序不用关心子程序如何,他们之间只要有通用的通讯机制就足够了.

建立接口

在C#程序中,接口是用来定义一个类的功能的.接口定义了预期的方法,属性,事件信息.为了使用接口,每个具体的函数必须严格按照接口的定义完成所描述的功能.列表一展示了上面例子程序的接口:IPlug.这个接口定义了四个方法:GetData,GetEditControl,Save和Print.这四个定义并没有描述具体是怎么完成的,但是他们保证了这个类支持IPlug接口,也就是保证支持这些方法的调用.

定制属性

在查看代码之前,讨论总是先得转移到属性定制上面.属性定制是.NET提供的一个非常棒的新特性之一,属性对于所有的编程语言都是一种通用的结构.举个例子,一个函数用于标识可访问权限的public,private,或者protect标志就是这个函数的一个属性.属性定制之所以如此让人兴奋,那是因为编程人员将不再只能从语言本身提供的有限的属性集中选择.一个定制的属性其实也是一个类,它从System.Attribute继承,它的代码被允许是自我描述的.属性定制可以应用于绝大多数结构中,包括C#里面的类,方法,事件,域和属性等等.示例代码片断定义了两个定制的属性:PlugDisplayNameAttribute和PlugDescriptionAttribute,所有的插件内部的类必须支持这两个属性.列表二是用于定义PlugDisplayNameAttribute的类.这个属性用于显示插件节点的内容.在程序运行的时候,主程序将可以利用反射(reflection)来取得属性值.

插件(Plug-Ins)

上面的示例程序包括了两个插件的执行.这些插件在EmployeePlug.cs和CustomerPlug.cs中定义.列表三展示了EmployeePlug类的部分定义.下面是一些关键点.

1.这个类实现了IPlug接口.由于主程序根本不会知道插件内部的类是如何定义的,这非常匾?主程序需要使用IPlug接口和各个插件通信.这种设计利用了面向对象概念里面的 »多态性 ».多态性允许运行时,可以通过指向基类的引用,来调用实现派生类中的方法.

2.这个类被两个属性标识,这样主程序可以判断这个插件是不是有效的.在C#中,要给一个类标识一个属性,你得在类的定义之前声明属性,内容附在括号内.

3.简明起见,例子只是使用了直接写入代码的数据.而如果这个插件是个正式的产品,那么数据总是应该放在数据库中或者文件中,各自所有的数据都应该仅仅由插件本身来管理.EmployeePlug类的数据在这里用EmployeeData对象来存储,那也是一个类型并且实现了IPlugData接口.IPlugData接口在IPlugData.cs中定义,它提供了最基础的数据交换功能,用于主程序和插件之间的通讯.所有支持IPlugData接口的对象在下层数据变化的时候将提供一个通知.这个通知实际上就是DataChanged事件的发生.

4.当主程序需要显示某个插件所含数据列表的时候,它会调用GetData方法.这个方法返回IPlugData对象的一个数组.这样主程序就可以对数组中的每个对象使用ToString方法得到数据以建立树的各个节点.ToString方法是EmployeeData类的一个重载,用于显示雇员的名字.

5.IPlug接口也定义了Save和Print方法.定义这两个方法的目的在于当有需要打印或者保存数据的时候,要通知一个插件.EmployeePlug类就是用于实现打印和保存数据的功能的.在使用Save方法的时候,需要保存数据的位置将会在方法调用的时候提供.这里假设主程序会向用户查询路径等信息.路径信息的查询是主程序提供给各个插件的服务.对于Print方法,主程序将把选项和内容传递到System.Drawing.Printing.PrintDocument类的实例.这两种情况下,和用户的交互操作都是一致的由主程序提供的.

反射(Reflection)

在一个插件定义好之后,下一步要做的就是查看主程序是怎么加载插件的.为了实现这个目标,主程序使用了反射机制.反射是.NET中用于运行时查看类型信息的.在反射机制的帮助下,类型信息将被加载和查看.这样就可以通过检查这个类型以判断插件是否有效.如果类型通过了检查,那么插件就可以被添加到主程序的界面中,就可以被用户操作.

示例程序使用了.NET框架的三个内置类来使用反射:System.Reflection.Assembly,System.Type,和System.Activator.

System.Reflection.Assembly类描述了.NET的程序集.在.NET中,程序集是配置单元.对于一个典型的Windows程序,程序集被配置为单一的Win32可执行文件,并且带有特定的附加信息,使之适应.NET运行环境.程序集也可以配置为Win32的DLL(动态链接库),同样需要带有.NET需要的附加信息.System.Reflection.Assembly类可以在运行的时候取得程序集的信息.这些信息包括程序集包含的类型信息.

System.Type类描述了类型定义.一个类型声明可以是一个类,接口,数组,结构体,或者枚举.在加载了一个类之后,System.Type类可以被用于枚举该类支持的方法,属性,事件和接口.

System.Activator类用于创建一个类的实例.

加载插件

列表四展示了LoadPlugs方法.LoadPlugs方法在HostForm.cs中定义,是HostForm类的一个private的非静态方法.LoadPlugs方法使用.NET的反射机制来加载可用的插件文件,并且验证它们是否符合被主程序使用的要求,然后把它们添加到主程序的树形显示区中.这个方法包含了下面几个步骤:

1.通过使用System.IO.Directory类,我们的代码可以用通配符来查找所有的以.plug为扩展名的文件.而Directory类的静态方法GetFiles能够返回一个System.String类型的数组,以得到每个符合要求的文件的物理路径.

2.在得到路径字符串数组之后,就可以开始把文件加载到System.Reflection.Assembly实例中了.建立Asdsembly对象的代码使用了try/catch代码块,这样如果某个文件并不是一个有效地.NET程序集,就会抛出异常,程序此时将弹出一个MessageBox对话框,告诉用户无法加载该文件.循环一直进行直到所有文件都已遍历完成.

3.在一个程序集加载之后,代码将遍历所有可访问到的类型信息,检查是否支持了HostCommon.IPlug接口.

4.如果所有类型都支持HostCommon.IPlug接口,那么代码继续验证这些类型,检查是否支持那些已预先为插件定义好的属性.如果没有支持,那么一个HostCommon.PlugNotValidException类型的异常将会被抛出,同样,主程序将会弹出一个MessageBox,告诉用户出错的具体信息.循环一直进行直到所有文件都已遍历完成.

5.最后,如果这些类型支持HostCommon.IPlug接口,也已定义了所有需要定义的属性,那么它将被包装为一个PlugTreeNode实例.这个实例就会被添加到主程序的树形显示区.

实现

主程序框架被设计为两个程序集.第一个程序集是Host.exe,它提供了主程序的Windows窗体界面.第二个程序集是HostCommon.dll,它提供了主程序和插件之间进行通信所需的所有类型定义.比如,IPlug接口就是在HostCommon.dll里面配置的,这样它可以被主程序和插件等价的访问.这两个程序集在一个文件夹内,同样的,附加的作为插件的程序集也需要被配置在一起.那些程序集被配置在plugs文件夹内(主程序目录的一个子文件夹).EmployeePlug类在Employee.plug程序集中定义,而CustomerPlug类在Customer.plug程序集中定义.这个例子指定插件文件以.plug为扩展名.事实上这些插件就是个普通的.NET类库文件,只是通常库文件使用.dll扩展名,这里用.plug罢了.特殊的扩展名对于程序运行是完全没有影响的,但是它可以让用户更明确的知道这是个插件文件.

设计的比较

并不是一定要像例子程序这样设计才算正确的.比如,在开发一个带有插件的C#程序时,并不一定需要使用属性.例子里使用了两个自定义的属性,其实也可以新定义两个IPlug接口的参数来实现.这里选择用属性,是因为插件的名字和它的描述在本质上确实就是一个事物的属性,符合规范.当然了,使用属性会造成主程序需要更多的关于反射的代码.对于不同的需求,设计者总是需要做出合理的决定.

总结

示例程序被设计为尽量的简单,以帮助理解主程序和插件之间的通信.在实际做产品的时候,可以做很多的改进以满足实用要求.比如:

1.通过对IPlug接口增加更多的方法,属性,事件,可以增加主程序和插件之间的通信点.两者间的更多的交互操作使得插件可以做更多的事情.

2.可以允许用户主动选择需要加载的插件.

avril 27th, 2006

Power Manager Suspend Time-outs

[Source : MSDN

The following list shows the registry values that control system power state transitions for the sample Power Manager:

  • ACUserIdle
  • ACSystemIdle
  • ACSuspend
  • BattUserIdle
  • BattSystemIdle
  • BattSuspend
  • BatteryPoll

These DWORD values are stored in the HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Power\Timeouts registry key. A value of 0 indicates that no time-out will occur. The sample implementation does not provide a method for bypassing OS power states; however, OEMs may choose to do so.

For the Power Manager to actively manage system power states, these settings need to be present in the registry. The actual decision to manage system power is based on the presence of ACUserIdle.

Note   To prevent conflicts between GWES and the Power Manager, you need to disable GWES power management as described previously. When the Power Manager is actively managing system power, it may restrict applications from entering arbitrary system power states.

You can reset the system state transition timers by creating a named auto-reset event called _T(« PowerManager/ReloadActivityTimeouts« ) and calling SetEvent on the handle of that event. This informs the Power Manager to read transition timer settings again from the Timeouts registry key.

Registry Settings

[HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlPowerTimeouts]

« ACUserIdle »=dword:3c; in seconds

« ACSystemIdle »=dword:12c; in seconds

« ACSuspend »=dword:0; in seconds

  »BattUserIdle »=dword:3c; in seconds

  »BattSystemIdle »=dword:b4; in seconds

  »BattSuspend »=dword:12c; in seconds

« BatteryPoll »=dword:1f4; battery polling interval, in milliseonds

janvier 4th, 2006

Get System Power Status

GetSystemPowerStatusEx

This function retrieves the power status of the system. The status indicates whether the system is running on AC or DC power, whether or not the batteries are currently charging, and the remaining life of main and backup batteries.

BOOL GetSystemPowerStatusEx(
PSYSTEM_POWER_STATUS_EX pstatus,
BOOL fUpdate );

Parameters

pstatus
[out] Pointer to the SYSTEM_POWER_STATUS_EX structure receiving the power status information.

fUpdate
[in] If this Boolean is set to TRUE, GetSystemPowerStatusEx gets the latest information from the device driver, otherwise it retrieves cached information that may be out-of-date by several seconds.
Return Values
This function returns TRUE if successful; otherwise, it returns FALSE.

Remarks
The GetSystemPowerStatusEx function is not supported for emulation.

Requirements
Runs on Versions Defined in Include Link to
Windows CE OS 1.0 and later Winbase.h
Pocket PC 2002 Windows CE OS 3.0 Winbase.h Winbase.h coredll.lib
Pocket PC Windows CE OS 3.0 Winbase.h Header Link to
Note This information applies to the version of the operating system as provided by Microsoft. Actual implementation is determined by the original equipment manufacturer (OEM) and some devices may not support this function.

SYSTEM_POWER_STATUS_EX
This structure contains information about the power status of the system.

typedef struct _SYSTEM_POWER_STATUS_EX {
BYTE ACLineStatus;
BYTE BatteryFlag;
BYTE BatteryLifePercent;
BYTE Reserved1;
DWORD BatteryLifeTime;
DWORD BatteryFullLifeTime;
BYTE Reserved2;
BYTE BackupBatteryFlag;
BYTE BackupBatteryLifePercent;
BYTE Reserved3;
DWORD BackupBatteryLifeTime;
DWORD BackupBatteryFullLifeTime;
} SYSTEM_POWER_STATUS_EX, *PSYSTEM_POWER_STATUS_EX, *LPSYSTEM_POWER_STATUS_EX;

Members

ACLineStatus

AC power status. It is one of the following values: Value Description
0 Offline
1 Online
255 Unknown status

All other values are reserved.

BatteryFlag
Battery charge status. It can be a combination of the following values: Value Description
1 High
2 Low
4 Critical
8 Charging
128 No system battery
255 Unknown status

All other values are reserved.

BatteryLifePercent
Percentage of full battery charge remaining. This member can be a value in the range 0 to 100, or 255 if status is unknown. All other values are reserved.

Reserved1
Reserved; set to zero.

BatteryLifeTime
Number of seconds of battery life remaining, or 0xFFFFFFFF if remaining seconds are unknown.

BatteryFullLifeTime
Number of seconds of battery life when at full charge, or 0xFFFFFFFF if full lifetime is unknown.

Reserved2
Reserved; set to zero.

BackupBatteryFlag
Backup battery charge status. It is one of the following values: BATTERY_FLAG_HIGH
BATTERY_FLAG_CRITICAL
BATTERY_FLAG_CHARGING
BATTERY_FLAG_NO_BATTERY
BATTERY_FLAG_UNKNOWN
BATTERY_FLAG_LOW

BackupBatteryLifePercent
Percentage of full backup battery charge remaining. Must be in the range 0 to 100, or BATTERY_PERCENTAGE_UNKNOWN.

Reserved3
Reserved; set to zero

BackupBatteryLifeTime
Number of seconds of backup battery life remaining, or BATTERY_LIFE_UNKNOWN if remaining seconds are unknown.

BackupBatteryFullLifeTime
Number of seconds of backup battery life when at full charge, or BATTERY_LIFE_UNKNOWN if full lifetime is unknown.

décembre 3rd, 2005

Le Nom « My Documents »

Sur le PPC, le nom de dossier "My documents" dépends de la langue de version de ROM. Voici la méthode d’eVC pour récupérer ce chemin: [Ref : MSDN]
SHGetSpecialFolderPath(NULL,szTxt,CSIDL_PERSONAL,0);

CSIDL_PERSONAL requests that the "My Documents" folder be returned in szTxt (TCHAR).

décembre 3rd, 2005

Comment trouver la carte de stockage?

Voici un morceau de code d’eVc qui cherche la carte de stockage:[ref: MSDN]

void ShowFlashCard()
{
BOOL bContinue = TRUE;
HANDLE hFlashCard;
WIN32_FIND_DATA lpwfdFlashCard;

hFlashCard = FindFirstFlashCard (&lpwfdFlashCard);
if (hFlashCard == INVALID_HANDLE_VALUE) return;

while (bContinue)
{
MessageBox( NULL, lpwfdFlashCard.cFileName,
TEXT(« FindFlash »), MB_OK );
bContinue = FindNextFlashCard ( hFlashCard,
&lpwfdFlashCard );
}

FindClose (hFlashCard); // Close the search handle.
}