Monday, August 29, 2005

Movie Link

http://www.caixiong.com/Statistic.aspx?ID=10388&Movie=影视专栏

Friday, August 26, 2005

Answers For Great Net Developer (3)

Answers For Great .Net Developer (3)
ASP.NET (UI) Developers


  • Describe how a browser-based Form POST becomes a Server-Side event like Button1_OnClick. After a button click event happened, the delegate will call a associated method with this event (this method is called event handler) . Common Scenario: Postback event--->page_Load(ispostback=false) ---> Buttoin_Click--->Raise Postback event--->Page_Load(ispostback=true, )-----> Call Event Handler method
  • What is a PostBack?

  • For server control to capture postback event, it must implant .IPostBackEventHandler Interfaces.

  • On postback, the page framework searches the post content and determines whether a posted name corresponds to the unique id of a server control that implements IPostBackEventhandler. If so, it invokes the RaisePostBackEvent method of that control.

  • What is ViewState? How is it encoded? Is it encrypted? Who uses ViewState?

  • In ASP, the state can not be stored in web. So have to use hidden fileld to store values.

  • ViewState is not only page based. It can be controlled in four levels: Machine , application(web.config), page, control.

  • Base64 formatted. Default is not encrypted but can be by adding some code. A convenient way to manage the state.

  • It can become pretty big if there are a lot of controls in the page or the control has a lot of information to store (like datagrid).

  • What is the <machinekey> element and what two ASP.NET technologies is it used for?

  • What three Session State providers are available in ASP.NET 1.1? What are the pros and cons of each?

  • What is Web Gardening? How would using it affect a design?

  • Given one ASP.NET application, how many application objects does it have on a single proc box? A dual? A dual with Web Gardening enabled? How would this affect a design?

  • Are threads reused in ASP.NET between reqeusts? Does every HttpRequest get its own thread? Should you use Thread Local storage with ASP.NET?

  • Is the [ThreadStatic] attribute useful in ASP.NET? Are there side effects? Good or bad?

  • Give an example of how using an HttpHandler could simplify an existing design that serves Check Images from an .aspx page.

  • What kinds of events can an HttpModule subscribe to? What influence can they have on an implementation? What can be done without recompiling the ASP.NET Application?

  • Describe ways to present an arbitrary endpoint (URL) and route requests to that endpoint to ASP.NET.

  • Explain how cookies work. Give an example of Cookie abuse.

  • A cookie is a piece of information sent to a browser by the server. Then browser sends it back to server. By this way, the server will remember the user old info like user name, age, etc .

  • Big cookies will affect the traffic of network and security issue.

  • Explain the importance of HttpRequest.ValidateInput()?

  • What kind of data is passed via HTTP Headers?

  • Juxtapose the HTTP verbs GET and POST. What is HEAD?

  • Name and describe at least a half dozen HTTP Status Codes and what they express to the requesting client.

  • How does if-not-modified-since work? How can it be programmatically implemented with ASP.NET?Explain <@OutputCache%> and the usage of VaryByParam, VaryByHeader.

  • How does VaryByCustom work?

  • How would one implement ASP.NET HTML output caching, caching outgoing versions of pages generated via all values of q= except where q=5 (as in http://localhost/page.aspx?q=5)?

Thursday, August 25, 2005

NoTouch Deployment in .Net (MSDN)

No-Touch Deployment in .NET
July 2002
Summary: This article demonstrates an exciting new feature to simplify deploying and updating a Windows Form Smart Client using a Web Server. The Task Management sample application referenced in this paper is provided in Visual Basic .NET. (12 printed pages)
Overview
Have you ever had to deploy a Visual Basic client server application? What about a Win32 application that relied on COM registration? Proper installation in a corporate desktop environment has been plagued with various issues. These range from simple problems like trying to get all of the users to upgrade to far more complicated DLL versioning problems.
Desktop applications have a number of advantages over Web applications, specifically:
  • Richer user interface (UI)

  • Responsiveness

  • Performance

  • Ability to run offline

  • Efficient use of edge resources (client machines)

  • Easy integration with local applications and APIs
In spite of these advantages, Web applications have gained tremendous popularity over the last few years due to the relative ease in which an application can be deployed and updated.  
With the .NET Framework, Microsoft set out to bring all the deployment and maintenance advantages of the Web application to the desktop application. DLL versioning problems are eliminated. By default, applications built using the .NET Framework are completely isolated from one another, retrieving their DLLs from their own private application directories. DLLs can still be shared among multiple applications, but instead of using the system registry for this, the shared DLLs are stored in the .NET Framework global assembly cache, which can host multiple versions of a given DLL and which keeps track of which version goes with which application. As for actually deploying the applications, the .NET Framework allows system administrators to deploy applications and updates to applications just as they would Web applications–via a remote Web server. This technology is called no-touch deployment and will be the focus of this document.
No-Touch Deployment using a Web Server
With no-touch deployment, Windows Forms applications (desktop applications built using the Windows Forms classes of the .NET Framework) can be downloaded, installed, and run directly on the users' machines without any alteration of the registry or shared system components.  
How does it work?
The .NET Framework installation provides a mechanism to hook Internet Explorer 5.01 and above to listen for .NET assemblies that are being requested. During a request, the executable will be downloaded to a location on disk called the assembly download cache. A process named IEExec will then launch the application in an environment with constrained security settings.
(image placeholder)
Figure 1. No-Touch Deployment Scenario
Let’s walk through a sample
We have a very straight forward Windows Forms application that let’s the user manage a list of tasks. These tasks could be used for bug tracking, IT ticket troubleshooting, or a To-do list similar to that found in Outlook XP or Visual Studio .NET.
Let’s first start off by taking a quick look at the application in Visual Studio .NET. The Task Management application is implemented in Visual Basic .NET using Windows Forms and an XML Web service named TaskMgmtWS which uses ADO.NET to communicate with an Access database to store the tasks.
(image placeholder)
Figure 2. Task Management Visual Studio .NET Solution
The task management application uses the TaskMgmtWS Web service to update a DataGrid windows control. The application starts by instantiating an XML Web service object named ws. Then, a call is made to the web method GetTasks() to get an ADO.NET DataSet of tasks. The tasks DataSet is then assigned to the DataSource property on our DataGrid windows control.
        ' Call the web service
        Dim ws As localhost.Service1 = New localhost.Service1()
        Dim ds As DataSet = ws.GetTasks()

        ' Wire up the Data Grid control with the resulting DataSet
        DataGrid1.DataSource = ds
        DataGrid1.DataMember = "Tasks"
When the application returns, the DataGrid is then updated and the application repaints. Figure 3 demonstrates the application running:
(image placeholder)
Figure 3. Task Management Windows Form
At this point, we have run into a common problem with a network based application. During the initial load, the application is making a network call that may take a few seconds to complete.
Improving the Windows Form Responsiveness
To improve the overall responsiveness of the application, we can take advantage of background threads. The updated application starts by invoking a worker thread to instantiate an XML Web service object. Once the web service has been instantiated, we use MethodInoker() to safely update the UI.
We start with the worker thread in the Form Load event:
        ' Use a background worker thread to make the Web Service call to
        ' improve the overall responsive of the application during the
        ' initial form load.
        ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf GetTasksWebServiceBackground))
For more information on updating a Windows Form in background threads, please visit the knowledge base article Q318604 entitled “Populate DataGrid on Background Thread with Data Binding by Using Visual Basic .NET” located at http://support.microsoft.com/default.aspx?scid=kb;en-us;Q318604.
While the Windows Form is running, we have a background thread that is working on the XML Web service call.
    Private Sub GetTasksWebServiceBackground(ByVal data As Object)
        ' Call the web service
        Dim ws As localhost.Service1 = New localhost.Service1()
        m_ds = ws.GetTasks()

        ' Update the Windows Form data grid
        Dim mi As New MethodInvoker(AddressOf UpdateDataGridForm)
        Dim ia As IAsyncResult = BeginInvoke(mi)
        Cursor = Cursors.Default
    End Sub
To demonstrate how to deploy the application to a Web Server, we are going to deploy the Task Management application to the Tasks Web Service Web folder. We start by changing the build folder to the TaskMgmtWS Web Service IIS virtual directory. This can be done by accessing the project properties for the TaskManagement Window Form project and then setting the Output path to “..\TaskMgmtWS\” as shown Figure 4.
(image placeholder)
Figure 4.  Task Management Build Options
With the build output path set to our web server, we can now deploy the application by simply recompiling. Once the application is built, we can now bring Internet Explorer and browse to the application http://localhost/TaskMgmtWS/TaskManagement.exe. Notice that Internet Explorer with the .NET Framework installed will not ask you to save the application, but rather will attempt to run it. If you need the ability to download an application from within a web page, you can use the “file://” protocol handler.
(image placeholder)
Figure 5. Run TaskManagement from Internet Explorer
The application is now pulled down via HTTP and installed into the assembly download cache. Before the application is run, the security policy will be checked to ensure the application has permission to conduct its operations.
(image placeholder)
Figure 6. TaskMangement Running From the Browser
So we have demonstrated how the application can be “run from a Web server”, let's now make a change to the application and see how easy it is to update. Selecting the DataGrid, we can use the Auto Format property to quickly change the background styles.
(image placeholder)
Figure 7. TaskManagement DataGrid Properties
The next step is to rebuild the application to update the exe on the Web server. The best part is that the application code is automatically updated when the user makes a request back to the Windows Form. The .NET Framework will automatically check the timestamp of the assembly to see if it needs to download again or if it can simply be run from the user’s assembly download cache. The updated application is illustrated in Figure 8:
(image placeholder)
Figure 8. Reload the application in Internet Explorer
Security
Code access security is the key to protecting the desktop from the Windows Forms applications that are being downloaded via no-touch deployment. This model works by matching applications to the permissions they should be assigned.  At runtime, the common language runtime gathers evidence on an assembly.  Evidence could take the form of what IE Zone the code came from (Local Disk, Intranet, Internet, Trusted Sites, Untrusted Sites), the URL the code originated from, any private key it is signed with, its hash value, an Authenticode publisher signature, etc.  Using this evidence, the common language runtime assigns the assembly to the appropriate Code Groups, or categories.  Each Code Group has a permission set assigned to it, dictating which permissions the assembly should get (ability to read from or write to the local disk, ability to access networked resources, ability, to print, ability to access environment variables, and so on).
By default, the .NET Framework ships with Code Groups set up around the IE Zones.  Code coming from the Intranet Zone, for example, gets a very constrained set of rights and may not perform File IO access.
To demonstrate the security checks in action, the Task Management executable contains a toolbar button named “Read Boot.ini” that attempts to access a file on C:\.
As a simple test, try clicking on the “Read Boot.ini” button to see what happens when the application request a file in the root of C:\. A security exception is thrown and the application will not process the request as shown in Figure 9:
(image placeholder)
Figure 9. .NET Security Exception
The exception returns a File IO permission exception indicating that application does not have access to that specific resource requested by TaskManagement.exe.
No-Touch Deployment with Multi-Assembly Applications
In this sample application, we have demonstrated how to load a single assembly. The .NET Framework also includes the ability to efficiently “trickle” multi-assembly applications to the client using the LoadFrom() method on an Assembly object.
The Assembly class has a LoadFrom method to initialize a reference to a particular assembly. The parameter for LoadFrom is either a URL or a file pathname. When a URL is specified, .NET first checks to see if the named assembly exists on the client by checking the assembly download cache. If the assembly is not in the assembly download cache, it is fetched from the Web server and a copy is placed in the download cache. Then the assembly object is ready for use in the code.
For instance, if the TaskManagement About Windows Form was implemented in a separate assembly named AboutForm.dll, we can use LoadFrom to pull down the assembly when the user makes a request to see the About dialog. By doing this, we are only transferring the code that is needed for the application as the user interacts with the application.
No-Touch Deployment and XML Web services
An important security limitation is that when an application is being distributed via the Web Server, its domain must match any of its Web Services that it relies on. For example if we launch TaskManagement.exe from http://myserver/TaskManagement.exe, it is only allowed to consume XML Web services on http://myserver. The application would not be allowed to call a Web service from another server for security reasons.
Optional: How to set the Security Policies
Administrators on a machine can change security permissions to grant more permission to an existing Code Group or to create new Code Groups from scratch.
Before proceeding, it is important to understand that changing security settings is dangerous and should never be turned off. In all cases, it is highly recommended to only change the security settings to make the application run.
To do this, if you are an administrator on your machine, you can run the CasPol command line tool (located at %SystemRoot%\Microsoft.NET\Framework\v1.0.3705\CasPol.exe) to grant applications launched from localhost full access to the local disk:
caspol -machine -addgroup All_Code -url http://localhost/* FullTrust -n TaskManagement
Now the application will be able to return the contents of Boot.ini because it has permission to perform File IO.
(image placeholder)
Figure 10. Boot.ini Contents
In addition to the CasPol command line tool, a graphical configuration tool, called the .NET Framework Configuration Tool, is provided via a Microsoft Management Console (MMC) Snap-in. After opening the snap-in, navigate to My Computer -> Runtime Security Policy -> Machine -> Code Groups -> All_Code -> TaskManagement to see the newly created code group. Try setting up a new Code Group to see how much flexibility and granularity is afforded by code access security.
(image placeholder)
Figure 11. .NET Framework Configuration MMC
Be sure to remove the Code Group created above after exploring the various options. This can be done by running the following command:
caspol -remgroup TaskManagement
You can also delete the new code group from the MMC tool by right clicking on TaskManagement and selecting delete as shown in Figure 12.
(image placeholder)
Figure 12. Remove TaskManagement Group
The tool allows you to easily generate an MSI file out of your Code Groups, which can then be rolled out across an enterprise using System Management Server or Group Policy, if desired.
Client requirements
  • Any operating system that supports the .NET Framework

  • .NET Framework with SP1

  • Internet Explorer 5.0.1 and above

  • Access to an IIS Web Server for application deployment
Conclusion
No-touch deployment provides an excellent vehicle for distributing Window Forms applications. An application developer can harness the full processing power of the desktop while maintaining the deployment and maintenance benefits realized by Web applications.
For More Information

Tuesday, August 23, 2005

Answers For Great .Net Developer (2)

Mid-Level .NET Developer
  • Describe the difference between Interface-oriented, Object-oriented and Aspect-oriented programming.
    Interface-oriented : a contract between two parities, not care the implentation. Example : COM
    Object-Oriented look at things behaviorally.(Methods and property)
    Aspect-oriented programming: It identifies the aspects of a program - separates out what's essential (functionality wise) and what's repetitive(or not so essential from functionality perspective).
  • Describe what an Interface is and how it’s different from a Class. Interface defines a contract not executable code. It is implemented by class.
  • What is Reflection?
    Discover which class/method/property they are in running time.
  • What is the difference between XML Web Services using ASMX and .NET Remoting using SOAP? (Not sure the answer)
    Web Service : Cross-Platform and interoperable
    .Net Remoting : extensible.
  • Are the type system represented by XmlSchema and the CLS isomorphic?
    don't know.
  • Conceptually, what is the difference between early-binding and late-binding?
    Data type is checked in compiling time for early-binding while it is in running time checked for late-binding.
  • Is using Assembly.Load a static reference or dynamic reference?
    Dynamic reference. The result will depend on different parameter with Assembly.Load
  • When would using Assembly.LoadFrom or Assembly.LoadFile be appropriate?
    don't know
  • What is an Asssembly Qualified Name? Is it a filename? How is it different?
    Assembly Qualified Name is strong name including “Assembly name”, “ version”,”public key ”.
    It is not a file name. Because it allows for signing and versioning.
  • Is this valid? Assembly.Load("foo.dll");
    No. The parameter should not be file name but (“file name + version number + public key token)
  • How is a strongly-named assembly different from one that isn’t strongly-named?
    The strongly named assembly usually is placed in GAC and is signed with using public/private key. It also has the version number and public key name. User then can identify different version assemblies.
  • How is a strongly-named assembly different from one that isn’t strongly-named?
    The strongly named assembly usually is placed in GAC and is signed with using public/private key. It also has the version number and public key name. User then can identify different version assemblies.
  • What is the JIT? What is NGEN? What are limitations and benefits of each?
    Just In Time. It allows for better compilation logic. But it needs long starup time.
    Native image generator. It allows for compile ahead of time and save the data type in the local cache of machine But because it does not know too much about data type. It may not be the perfect compiling logic. Faster starup time.
  • How does the generational garbage collector in the .NET CLR manage object lifetime? What is non-deterministic finalization?
    Three generational collector are defined in .Net CLR manage object life time: 1.short lived . 2 and 3 are long term lived.
    Non-deterministic finalization means the object ‘s memory is not instantly released when this object is out of scope. The system will determine when to release all the memory for this object.
  • What is the difference between Finalize() and Dispose()?
    Finalize is automatically called by system when object destroyed .(should only call Finalize when you explicitly release object )
    To control resources outside CLR , such as window handlers or data connection ,and support Garbage collection, .Net using Dispose to release objects.(Dispose has to be called by user not automatically )
  • How is the using() pattern useful? What is IDisposable? How does it support deterministic finalization?
    Make it hard to forget to release system resource. When out of “ using” scope, the current object’s Dispose method is automatically called to release resource. It is not for memory but only for GC.
    IDisposable is an interface to define a way to dispose of objects in a deterministic manner.
  • What does this useful command line do? tasklist /m "mscor*"
    Display all the current tasks having dll like “mscor*” loaded.
  • What is the difference between in-proc and out-of-proc?
    In-proc means all the functions are running in current local process.
    Out-of-proc means the functions are running in different process.
    in-proc means the component is compiled as a shared library file like .dll Out-of-proc means the component is compiled as executable file like .exe. To call the out-of-proc component, the marshalling is needed between two processes and thus slower
  • What technology enables out-of-proc communication in .NET?
    Remoting. Remoteing enable user to use any other object in current computer or any other computer available in its network.while an out-of-proc can be implanted in any number of other ways,someone using the term almost always means Remoting..
  • When you’re running a component within ASP.NET, what process is it running within on Windows XP? Windows 2000? Windows 2003?
    Aspnet_wp.exe ( the following is the process flow for a regular http requests:HttpRequest--->Inetinfo.exe-->AspNet_ISAPT.dll--->Aspnet_wp.exe---> HttpRuntime-->HttpApplication Factory-->HttpApplication-->HttpModule-->HttpHandler Factory-->HttpHandler-->HttpHandler.ProcessRequest()
    Inetinfo.exe if in debug mode(Inetinfor.exe is primarily used for debugging IIS)

Sunday, August 21, 2005

UML Basic

UML Basic
     Difference between UML and design pattern in enterprise architecture

  • There are five phases in enterprise architecture: Envisioning, Planning, Designing, Stabilizing (Testing), Deploying.

  • Envisioning: Preparing three documents of envisioning phase

  • Vision/Scope document

  • Risk Access document

  • Project Structure

  • Planning:

  • Gathering and Analyzing Business and User Requirements

  • Formalizing Business Requirements into Functional Specifications

  • Transforming requirements into functional specifications

  • Transforming functional specifications to technical specifications.

  • Designing:

  • Conceptual

  • Logical

  • Physical :eight items should be concerned during this phase

  • Performance

  • Maintainability

  • Extensibility

  • Scalability

  • Availability

  • Deploy ability

  • Security

  • Accessibility

  • Establish Standard ,process, quality and performance metrics

  • Code Standard: source code formatting and naming conventions

  • Real example:

  • Finish all user case models

  • Base class diagram

  • Sequence diagram

  • Collaboration diagram

  • Detailed class diagram

  • Stabilizing(Testing)

  • Unit test

  • System test

  • Pilot test

  • Deployment

  • Design pattern includes 23 programming patterns are usually used in Designing phase (conceptual, logical).

  • UML is design method to represent the elements (including current design patterns) of business models.(It is just a way to show all the elements )

  • Datebase Design:

  • ER

  • ORM (object role modeling)

  • Difference between ER and ORM

  • For years, ER modeling has been one of the most popular conceptual modeling languages for database design. ER models are still useful for documenting the conceptual design of a system but are far less useful for formulating that design or making and applying changes to it. In fact, the ORM model still includes a use for ER but only as one “view” of the conceptual data model

  • ORM is a system based on natural language because instead of creating its own notation for describing the database of a system, it uses English. ORM is similar to another natural language design methodology called Natural Language Information Analysis Method (NIAM) and is partly based on that meth

  • There are other benefits to using ORM instead of ER as well. ORM allows database designers to provide more detail about the design in the diagrams and simplify the addition of constraints to the model. In short, the creator of ORM analyzed the modeling languages that came before it and created a language that overcomes many of the deficiencies of those languages while retaining their simplicity.

  • UML is one kind of design method of OOA/D (Object Oriented Analysis/Design)

  • UML is a language to represent unified best engineering practices for specifying, visualizing, constructing, documenting the elements of business models, software systems. On the other hand, it is not a process, visual programming language.

  • Enterprise Architecture (EA), RUP and Microsoft Visio are all development tools of UML. (Or can say “UML can support a number of methodologies such as RUP, Visio”.)

  • The reason using UML is mainly for RAD (rapid application development)

  • UML supports nine types of diagrams :

  • Activity (mostly used): An activity diagram is a special case of a statechart diagram in which all of the states are action states and the flow of control is triggered by the completion of actions in the source state.

  • Collaboration: A collaboration diagram represents a collaboration, which is a set of object roles related in a particular context, and an interaction, which is the set of messages exchanged among the objects to achieve an operation or result. It is an interaction diagram that shows, for one system event defined by one use case, how a group of objects collaborate with one another.

  • Component: component diagrams are implementation-level diagrams that show the structure of the code itself. A component diagram consists of components, such as source code files, binary code files, executable files, or dynamic-link libraries (DLLs), connected by dependencies.

  • Deployment: Deployment diagrams are implementation-level diagrams that show the structure of the run-time system. From a deployment diagram, you can understand how the hardware and software elements that make up an application will be configured and deployed.

  • Package: A package is the basic organizing element of a UML system model. You can think of the entire system as a package that contains all the other packages, diagrams, and elements. One package can contain subordinate packages, diagrams, or single elements, and you can set the visibility of a package as well as the visibility of the elements it contains

  • Sequence: A type of interaction diagram, a sequence diagram shows the actors or objects participating in an interaction and the events they generate arranged in a time sequence. Often, a sequence diagram shows the events that result from a particular instance of a use case but a sequence diagram can also exist in a more generic form.

  • Statechart : A statechart diagram represents a state machine. By documenting events and transitions, a statechart diagram shows the sequence of states an object goes through during its life

  • Static(mostly used) :

  • Conceptual static: A conceptual diagram is a static structure diagram that represents concepts from the real world and the relationships between them. It focuses on relationships and attributes rather than methods, and helps you understand the terminology in the domain area for which you are developing a system.

  • Class static(ER diagram ): Like conceptual diagrams, class diagrams are static structure diagrams that decompose a software system into its parts. In a class diagram, however, the parts are classes that represent fully defined software entities rather than objects that represent real-world concepts.

  • User Case (mostly used): After you identify the use cases, you can create use case diagrams to put the use cases in context. Creating a use case diagram involves establishing a system boundary for a set of use cases and defining the lines of communication between a particular actor and a use case. In the early stages of a development project, use case diagrams describe real-world activities and motivations. You can refine the diagrams in later stages to reflect user interface and design details.
Example: Analyze A real business problem and design a solution using UML. (can see Beginners_Guide_to_UML_Part2.pdf)



Application Block Introduction

Application Block Introduction (From CSDN)

数据访问应用程序模块(Data Access Application Block)
2002年4月发布1.0版,2002年6月发布2.0版
它能够实现数据访问帮助组件——SqlHelper,后者会有助于通过公开一组静态方法对7.0以及更高版本的SQL服务器执行陈述式,并能够减少你必须编写的数据访问代码的数量。2.0版支持1.1版的.NET框架。
如果你正在将SQL服务器作为数据库,并希望减少你所编写的数据访问代码的数量,那么你就要使用它。你可以在自己数据访问类的内部使用它。使用C#编写的用于OleDb和Oracle的SqlHelper包含在Nile 3.0实例应用程序里。
异常管理应用程序块(Exception Management Application Block)
2002年4月
它能够通过ExceptionManager类为异常信息的发布提供一个简单和灵活的机制。它还支持过滤和创建你自己的异常发布器,从而将数据发布给源,而不是使用文本和XML的文件和事件日志。它还提供从其衍生出的一个BaseApplicationException类,用以收集其他的环境信息。
你应该将它用作自己异常处理框架的基础。它适用于使用异常链接(exception chaining)并将异常传递给调用栈(call stack)的应用程序。自定义的发布器能够被用来将异常信息记录到共享数据库里。
采集应用程序块(Aggregation Application Block)
2003年6月
它是一个将服务代理(Service Agent)分派出去从各种用于应用程序的源收集信息的组件。然后应用程序就请求采集组件(aggregate component),并返回一个所收集数据的XML文档。它使用异常管理块,并能够同异步块(Asynchronous Block)和缓冲块(Caching Block)一起使用。
当你的应用程序需要将数据从各种源收集到一起,而且这些源会随着时间的推移而改变的时候,你就要使用它。采集块用于底层数据源的抽象。
异步调用应用程序块(Asynchronous Invocation Application Block)
2003年6月
它是一个将请求分派给背景线程,然后在完成的时候通知应用程序的组件。它使用异常管理和数据块(Exception Management and Data block)。这个块的目的就是为了同采集块(Aggregate Block)一起使用,并能够同缓冲块(Caching block)一起工作。
当你的应用程序所通信的数据源需要一个冗长调用(lengthy call)的时候,你需要使用它。使用异步块(Async Block)会让应用程序响应更快,就好像通过允许Web页面逐渐建立而取得的效果一样。
缓冲应用程序块(Caching Application Block)
2003年6月
它允许应用程序请求CacheManager对象,后者会返回数据或者调用一个服务代理来取回它。它允许项目从缓冲里超期失效,并允许被缓冲数据以多种格式保存,包括SQL服务器的内存映射文件,或者Singleton对象。它同时使用异常管理和数据块。它还能够同异步块和采集块一起使用。
当你需要缓冲Windows窗体里或者其他基于非Web应用程序里的数据时,你就要使用它。ASP.NET提供了它自己的缓冲区,因此Web应用程序一般都不需要它。它对于提高性能很有用处。
配置管理应用程序块(Configuration Management Application Block)
2003年6月
它是一个将用在应用程序里的配置信息的位置进行抽象,并加入加密、缓冲和可扩展性等特性的组件。它还加入了读写配置数据的能力。
当你的应用程序要求其配置数据在不同的时间被保存到不同的位置时,你需要使用它。而且利用它可以加密敏感信息。
更新应用程序块(Updater Application Block)
2003年6月
它是一个能够被用来将新版本应用程序下载到客户机器上(例如使用BITS)的组件。它包括一个声明,用来指定所有相关的文件,并确保整个应用程序都被下载下来了。它对自定义的下载提供了可选的文件验证和支持,还提供了验证组件。它使用异常管理块。
当你的应用程序需要自动升级新组件,或者当你正在编写某项服务以向客户机器提供到各种应用程序的升级时,你需要使用它。
用户界面处理应用程序块(User Interface Process Application Block)
2003年6月
它是一个能够让你将用户处理的逻辑和状态同搜集数据以及导航所需的用户界面分离开的基本类(ControllerBase)和用户界面处理管理器组件。它包括一组存储管理器(persistence manager),后者允许你将处理的状态保存在SQL服务器、ASP.NET会话或者自定义存储里。
当你需要在不同类型的应用程序(Windows窗体、Web表单)里实现同一种处理,或者想要允许用户在以后能够恢复到会话里的时候,你需要使用它。它很适合于基于安装向导的应用程序。

Mostly Used Design Patterns

We all know there are total 23 regular design patterns so far which are about design and interaction of objects, as well as providing communication platform concerning elegant, reusable solutions to commonly encountered programming challenges. According to individual behavior and functionality, there are three categories:
Creational Factory, Structural Factory, Behavior Factory.

Pattern Lists

  • Highly Used (7): Singleton, Composite, Façade, Proxy, Iterator, Observer, Template.
  • Medium Used (6): Abstract Factory, Factory, Strategy , Adapter , Command , State .
  • Low Used (4) : Builder, Bridge , Decorator , Chains of Responsibility .
  • Seldom Used (6) : Prototype, Flyweight , Interpreter , Mediator , Memento , Visitor

Combined pattern: MVC

MVC pattern is a combined pattern including three patterns:


  • The relationship between Model and View is Observer

  • The views can be nested: Composite

  • The relation ship between View and Controller is Strategy


Creational Factory:



  • Abstract Factory:
(image placeholder)



  • Factory:

  • (image placeholder)




  • Singleton: ****

  • (image placeholder)
Structure Factory:




  • Adapter:

  • (image placeholder)

  • Composite:***

  • (image placeholder)

  • Decorator:

  • (image placeholder)

  • Façade: ***((the current system has some subsystems which can be both simple and complicated .(image placeholder)




  • Proxy:***

  • (image placeholder)

  • Behavioral Factory:

  • Command pattern:

  • (image placeholder)




  • Iterator pattern: ***




  • (image placeholder)

  • Observer Pattern:***

  • (image placeholder)




  • State:

  • (image placeholder)

  • Strategy:

  • (image placeholder)




  • Template Method:***

  • (image placeholder)

  • Strategy

  • (image placeholder)

Saturday, August 20, 2005

Duwamish

Duwamish部署方案篇

Duwamish 7.0 支持两种多计算机部署方案。非分布式部署方案在一台 Web 主机上部署 Web 层、业务外观、业务规则和数据访问层,但可以在群集间复制该 Web 主机以达到负载平衡。分布式方案在单独的服务器上部署特定的组件。例如,业务外观、业务规则和数据访问层可能位于独立于 Web 主机的服务器上。在实际部署中数据库服务器通常位于单独的计算机上。

1, 非分布式部署方案
在一台 Web 主机上部署 Web 层、业务外观、业务规则和数据访问层,然后通过软件(如Application Center 2000)或硬件来实现网络场(Web Farm)内各个Web Server的负载平衡。

在本机默认安装Duwamish 7.0时,是采用非分布式部署方案。

2, 分布式部署方案
使用 .NET Framework 远程处理技术将应用程序分布到多台计算机中。简单而言,就是IIS Web ServerApplication Server分离,其中Web层(包括SystemFrameworkCommon项目)部署在IIS Web上,BusinessFacde/BusinessRules/DataAccess层(包括SystemFrameworkCommon项目)一起部署在Application Server上。
(image placeholder)
 
Duwamish 7.0 使用 HTTP/二进制而不是 HTTP/SOAP。使用 HTTP 的决定基于要通过端口 80 上的防火墙的要求。使用二进制而不是 SOAP 的决定基于性能上的考虑。对于大的数据块,二进制的性能优于 SOAP。因此,如果要传递大的数据块(例如,数组、数据集或数据表),则使用二进制格式化程序。如果要传递小的数据块,则选择使用 SOAP 还是二进制格式化程序是无关紧要的。传递整数时两者的性能都很好。

3, 如何将Duwamish 7.0部署为基于.Net Remoting的分布式系统
下面采用Microsoft提供的Deploytool工具自动进行(其实手工也很方便):
C:\Program Files\Microsoft Visual Studio .NET 2003\Enterprise Samples\Duwamish 7.0 CS>deploytool deploy RemoteMachine=localhost path="C:\Program Files\Microsoft Visual Studio .NET 2003\Enterprise Samples\Duwamish 7.0 CS\Duwamish7_Remote"  
command line窗口输入上述命令行代码。

[10/29/2004 6:43:43 AM] Creating directory C:\Program Files\Microsoft Visual Studio .NET 2003\Enterprise Samples\Duwamish 7.0 CS\Duwamish7_Remote on W1MIS38
[10/29/2004 6:43:43 AM] Stopping all internet services on W1MIS38
[10/29/2004 6:43:59 AM] Deploying Duwamish7 Business Facade on W1MIS38
[10/29/2004 6:43:59 AM] Creating web site on W1MIS38
[10/29/2004 6:44:00 AM] Generating remoting configuration files
[10/29/2004 6:44:00 AM] Starting all internet services on W1MIS38
[10/29/2004 6:44:02 AM] Starting Default Web Site on W1MIS38
[10/29/2004 6:44:02 AM] Deployment successful

运行结果:
1)在IIS创建中创建Web ApplicationDuwamish7_Facade),本地路径为:C:\Program Files\Microsoft Visual Studio .NET 2003\Enterprise Samples\Duwamish 7.0 CS\Duwamish7_Remote\web 作为Remote Server端,Bin目录下是BusinessFacde/BusinessRules/DataAccess层(包括SystemFrameworkCommon项目)DLL文件。
其中web.config文件中包含所有Remote Objects的配置,如
<wellknown mode="Singleton" type="Duwamish7.BusinessFacade.ProductSystem, Duwamish7.BusinessFacade" objectUri="ProductSystem.rem" />

2Web层创建remotingclient.cfg配置文件,对Application Server而言,Web层相当与Client端。
remotingclient.cfg配置文件中包含formatter的设置(binary ),选择二进制格式化程序来序列化消息,注意是出于性能的考虑。

3Web application加载remotingclient.cfg配置文件
Web applicationglobal.asax文件包括如下代码,在Application_OnStart事件中加载Retmoting配置文件。
void Application_OnStart()
{
ApplicationConfiguration.OnApplicationStart(Context.Server.MapPath( Context.Request.ApplicationPath ));
string configPath = Path.Combine(Context.Server.MapPath( Context.Request.ApplicationPath ),"remotingclient.cfg");
if(File.Exists(configPath))
    RemotingConfiguration.Configure(configPath);
}

其中前面代码ApplicationConfiguration.OnApplicationStart()是调用Duwamish7.SystemFramework.ApplicaitonConfigurationOnApplicationStart()方法,用来初始化application root和读取web.config中的配置信息(将在Duwamish代码分析篇》中进行具体分析)。

DuwamishMicrosoft提供一个企业级的分布式系统架构,如果开发企业级的分布式系统,可以模仿这种架构,如果是开发一些简单的系统,则完全可以简化。
 
以前也学习过Duwamish范例,只是发现不同时间,不同经历,有不同的体会。正如卢彦所说的一样:通过研究Duwamish示例,高手能够领悟到.Net应用架构的设计思想,低手能够学习到.Net的编程技巧,实在是老少皆宜。
 
因此,这里再次学习并体验一次Duwamish范例。
 
1Duwamish 7.0 结构分为四个逻辑层(FROM MSDN):
Web 层 - Presentation
Web 层为客户端提供对应用程序的访问。这一层是作为 Duwamish.sln 解决方案文件中的 Web 项目实现的。Web 层由 ASP.NET Web 窗体和代码隐藏文件组成。Web 窗体只是用 HTML 提供用户操作,而代码隐藏文件实现各种控件的事件处理。
业务外观层 - Business Facade
业务外观层为 Web 层提供处理帐户、类别浏览和购书的界面。这一层是作为 Duwamish.sln 解决方案文件中的 BusinessFacade 项目实现的。业务外观层用作隔离层,它将用户界面与各种业务功能的实现隔离开来。除了低级系统和支持功能之外,对数据库服务器的所有调用都是通过此程序集进行的。
业务规则层 - Business Rules
业务规则层是作为 Duwamish.sln 解决方案文件中的 BusinessRules 项目实现的,它包含各种业务规则和逻辑的实现。业务规则完成如客户帐户和书籍订单的验证这样的任务。
数据访问层 - Data Access
数据访问层为业务规则层提供数据服务。这一层是作为 Duwamish.sln 解决方案文件中的 DataAccess 项目实现的。
 
除了上述四个逻辑层外,Duwamish 7.0 还包含封装在 Duwamish.sln 解决方案文件中的 Common 项目内的共享函数。“通用”(Common) 层包含用于在各层间传递信息的数据集。Common 项目还包含 Duwamish.sln 解决方案文件中的 SystemFramework 项目内的应用程序配置和跟踪类。
 
2,各个逻辑层之间的关系图(FROM MSDN)及其调用Sequeance图示例:(image placeholder)
下面是Categories.aspx web页面获取CategoryDescription的整个调用过程。
1)实例化ProductSystem对象
2)调用ProductSystemGetCategories()方法
3)检测参数的合法性
4)创建Categories::DataAccess对象实例
5)返回上述对象
6)调用Categories::DataAccess对象的GetCategories()方法
7)创建CategoryData::Common对象实例
8)返回上述对象
9)返回CategoryData::Common对象实例,该实例中已经包含了需要的数据
10)返回CategoryData::Common对象实例给web/Client
11)检测数据的合法性
12)读取并显示结果:CategoryDescription
(image placeholder)
SystemFramework项目包含一些application需要的配置参数,ApplicationLog日志类和ApplicationAssert参数校验类。SystemFramework项目为所有其他的项目所引用。
 
Common项目包含了用于在各层间传递信息的数据集,如上述的CategoryData继承System.Data.DataSet,既不是所谓的typed DataSet,也不是一般的DataSet,不过简单实用,这是基于.Net Remoting开发分布式系统用来tiertier之间交互数据的一种方法。Common项目也被其他的项目引用,SystemFramework项目除外。
 
BusinessFacade项目中所有的Classes继承MarshalByRefObject class,显然是让准备将BusinessFacade tier部署为Remote Objects。不过,实际上默认这里并没有将其部署为Remote ObjectsWeb层仍然调用本地对象(《Duwamish部署方案篇》将分析这个问题)。
 
3Summary
 
在开发基于.Net Framework企业级分布式系统时,上述架构值得推荐,但也并非完美无暇,实际上存在一些值得改进的地方。显然,不可能一个范例适合所有的实际情况么,要求太苛刻了。其实,Enterprise Samples中的另外一个范例Fitch and Mather 7.0,其架构和Duwamish就有些不同了。
 
如果是开发本地的系统,就不要模仿Duwamish架构(看看上面获取CategoryDescription调用过程就知道了,太费劲。),如Business FacadeBusiness RulesClasses应采用fine-grained interface设计,层与层之间的交互参数也不必全部采用DataSet,适当的时候采用setter/getter就可以了,这样不仅可以提高开发效率,而且有助于提高performance, maintainability and reusability

Duwamish代码分析篇
 
Written by: Rickie Lee
Nov. 02, 2004
 
继续前面的2POSTDuwamish架构分析篇》Duwamish部署方案篇》,这里在代码层次上分析Duwamish  7.0范例,主要目的是解析Duwamish范例中值得推荐的编码风格和提炼出可以重用的代码或Class
 
1,读取配置文件类-SystemFramework\ApplicationConfiguration.cs
ApplicationConfiguration类用来读取web.config文件中自定义section的配置信息,初始化一些基本设置。
ApplicationConfiguration类实现IconfigurationSectionHandler接口,并需要实现[C#]
object Create(
   object parent,
   object configContext,
   XmlNode section
)方法,以分析配置节的 XML。返回的对象被添加到配置集合中,并通过 GetConfig 访问。
 
 
部分代码片断解释:
1Code Snippet 1 – ApplicationConfiguration. OnApplicationStart()方法
public static void OnApplicationStart(String myAppPath)
{
    appRoot = myAppPath;
    System.Configuration.ConfigurationSettings.GetConfig("ApplicationConfiguration");
    System.Configuration.ConfigurationSettings.GetConfig("DuwamishConfiguration");
    System.Configuration.ConfigurationSettings.GetConfig("SourceViewer");      
}
ConfigurationSettings 类还提供了一个公共方法ConfigurationSettings.GetConfig() 用于返回用户定义的配置节的配置设置,传入的参数section name,如"ApplicationConfiguration",表示要读取的配置节。
 
NameValueCollection nv=new NameValueCollection();
//实例化NameValueCollection 类对象
nv=(NameValueCollection)ConfigurationSettings.GetConfig("ApplicationConfiguration ");
//返回用户定义的配置节的设置
return nv["SystemFramework.Tracing.Enabled"].ToString();
//返回特定键值,如SystemFramework.Tracing.Enabled
 
不过,ConfigurationSettings.GetConfig()方法在调用时,自动调用Create()方法,可以看到ApplicationConfiguration.Create()方法正是用来读取指定section的配置,并初始化设置参数。
 
Global.asax Application_OnStart 事件处理程序向 SystemFramework ApplicationConfiguration OnApplicationStart 方法发出调用,正是上述的代码片断。
 
2Code Snippet 2 Global.asaxApplication_OnStart()方法
void Application_OnStart()
{
    ApplicationConfiguration.OnApplicationStart(Context.Server.MapPath( Context.Request.ApplicationPath ));
    string configPath = Path.Combine(Context.Server.MapPath( Context.Request.ApplicationPath ),"remotingclient.cfg");
    if(File.Exists(configPath))
        RemotingConfiguration.Configure(configPath);
}
该方法肩负二大任务:(1)调用ApplicationConfiguration.OnApplicationStart()方法,并传入application的根目录(Root Directory)。(2)检测Client端的remoting配置文件是否存在(其实是web server端),如果存在,则读取并初始化remoting配置信息,如配置通道Channel等等,详见《Duwamish部署方案篇》。
 
2,读取web.configDuwamish相关的一些配置-Common\DuwamishConfiguration.cs
Common\DuwamishConfiguration.cs也实现IconfigurationSectionHandler接口,与SystemFramework\ApplicationConfiguration.cs类相似。
 
DuwamishConfiguration配置节包括如下一些配置信息:
Database connection stringDatabase连接串)Duwamish.DataAccess.ConnectionString,是否允许页面缓存Duwamish.Web.EnablePageCache,页面缓存过期时间Duwamish.Web.PageCacheExpiresInSeconds,是否允许SSL连接Duwamish.Web.EnableSsl等等。
 
如上所述,调用DuwamishConfiguration Class 是由SystemFramework\ApplicationConfiguration.csOnApplicationStart()方法完成的:
System.Configuration.ConfigurationSettings.GetConfig("DuwamishConfiguration");
 
看看页面缓存配置在web page中如何使用的(web\book.aspx.cs文件为例):
//
// If everything succeeded, then enable page caching as indicated
// by the current application configuration.
//
if ( DuwamishConfiguration.EnablePageCache )
{
    //Enable  Page Caching...
    Response.Cache.SetExpires ( DateTime.Now.AddSeconds(DuwamishConfiguration.PageCacheExpiresInSeconds));
    Response.Cache.SetCacheability(HttpCacheability.Public);
}
Page_Load事件中最后判断是否允许页面缓存。
 
3,验证数据合法性类-SystemFramework\ApplicationAssert.cs
SystemFramework\ApplicationAssert.cs Class用来进行错误检测,并调用SystemFramework\ApplicationLog.cs Class记录错误日志。
 
学习其中的部分代码片断:
1Code Snippet 1 – Check Method
[ConditionalAttribute("DEBUG")]
public static void Check(bool condition, String errorText, int lineNumber)
{
    if ( !condition )
    {
        String detailMessage = String.Empty;
        StringBuilder strBuilder;
        GenerateStackTrace(lineNumber, out detailMessage);
        strBuilder = new StringBuilder();
        strBuilder.Append("Assert: ").Append("\r\n").Append(errorText).Append("\r\n").Append(detailMessage);
        ApplicationLog.WriteWarning(strBuilder.ToString());
        System.Diagnostics.Debug.Fail(errorText, detailMessage);
    }
}
 
[ConditionalAttribute("DEBUG")]定义Check()方法为conditional method,如果预处理符号(preprocessor symbol)没有定义,compiler不仅忽略该方法,而且忽略对该方法的调用,和#if DEBUG / #else / #endif有些类似。
 
该方法用来判断条件condition是否为true,如果为false,则调用SystemFramework\ApplicationLog.WriteWarning()方法记录错误日志。
 
2Code Snippet 2 – CheckCondition Method
public static void CheckCondition(bool condition, String errorText, int lineNumber)
{
    //Test the condition
    if ( !condition )
    {
        //Assert and throw if the condition is not met
        String detailMessage;
        GenerateStackTrace(lineNumber, out detailMessage);
        Debug.Fail(errorText, detailMessage);
 
        throw new ApplicationException(errorText);
    }
}
 
该方法一般用来在进行前置条件判断,如conditionfalse,则抛出exception
 
4log日志类-SystemFramework\ApplicationLog.cs
ApplicationLog 类实现 Duwamish 7.0 中的记录和跟踪。Web.Config 文件中的配置设置确定是输出到 EventLog 文件、跟踪日志文件还是两者。下面是 Web.Config 文件中的 <ApplicationConfiguration> 节,它指定 EventLog 设置:
 
<ApplicationConfiguration>
    <!-- Event log settings -->
    <add key="SystemFramework.EventLog.Enabled" value="True" />
    <add key="SystemFramework.EventLog.Machine" value="." />
    <add key="SystemFramework.EventLog.SourceName" value="Duwamish7" />
    
    <add key="SystemFramework.EventLog.LogLevel" value="1" />
    <!-- Use the standard TraceLevel values:
             0 = Off
             1 = Error
             2 = Warning
             3 = Info
             4 = Verbose -->
Web.Config 文件的同一节还指定跟踪配置。Duwamish 7.0 跟踪日志的默认位置是:[安装 Visual Studio .NET 的驱动器号]:\Program Files\Microsoft Visual Studio .NET 2003\Enterprise Samples\Duwamish 7.0 CS\Web\DuwamishTrace.txt
 
在实际的应用系统开发中,用来提供Log功能的类应该比这个ApplicationLog类要好,这样就不去分析了,如Microsoft Exception Management Application Block就不错。
 
5Web.config配置文件-使用Web.congfig文件存储application设置
Duwamish 7.0 通过使用 Forms 身份验证来实现安全性。Forms 身份验证将未经授权的用户重定向到Web 窗体,该窗体提示用户输入其电子邮件地址和密码。
 
1)配置 Forms 身份验证
Web.config 文件中的设置配置 Forms 身份验证。对于 Duwamish 7.0Web.Config 文件按如下所述指定 Forms 身份验证的使用:
    <authentication mode="Forms">
      <forms name=".ADUAUTH" loginUrl="secure\logon.aspx" protection="All">
      </forms>
    </authentication>
    <authorization>
      <allow users="*" />
    </authorization>
 
authentication元素只能在计算机、站点或应用程序级别声明。如果试图在配置文件中的子目录或页级别上进行声明,则将产生分析器错误信息。
 
如上所示,Web.Config .ADUAUTH 指定为身份验证 Cookie 的名称。当用户请求受限资源时,公共语言运行库将未经授权的用户重定向到在上面的 Web.Config 设置中指定的Login.aspxprotection="All" 设置指定应用程序使用数据验证和加密来保护 Cookie。若要进一步限制资源,Duwamish 7.0 会将安全资源放置到名为 secure 的子文件夹中并使用额外的 Web.Config 文件(在secure文件夹),在该文件中指定只有经过身份验证的用户才可访问该子文件夹的内容。
    <authorization>
      <deny users="?" />
      <allow users="*" />
    </authorization>
 
<deny users="?" /> 标记指定拒绝对所有匿名用户的访问。<allow users="*" /> 标签允许访问所有已验证身份的用户。
 
经过secure\logon.aspx认证通过的请求,重新定向最初的URL
// 将已验证身份的用户重定向回最初请求的 URL
FormsAuthentication.RedirectFromLoginPage("*", false);
 
2)用户定义的配置节
  <configSections>
    <section name="ApplicationConfiguration" type="Duwamish7.SystemFramework.ApplicationConfiguration, Duwamish7.SystemFramework" />
    <section name="DuwamishConfiguration" type="Duwamish7.Common.DuwamishConfiguration, Duwamish7.Common" />
    <section name="SourceViewer" type="System.Configuration.NameValueSectionHandler, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
  </configSections>
 
section元素包含配置节声明,name 指定配置节的名称,type 指定从配置文件中读取节的配置节处理程序类的名称。配置节处理程序(即实现 IConfigurationSectionHandler 接口的类)读取设置。
 
上面定义了3个配置节处理程序:Duwamish7.SystemFramework.ApplicationConfiguration
Duwamish7.Common.DuwamishConfiguration
System.Configuration.NameValueSectionHandler
 
前面两个配置节处理程序是由application提供的,后面的System.Configuration.NameValueSectionHandler.Net Framework提供的,该类也实现了IconfigurationSectionHandler接口,用来提供配置节中的名称/值对配置信息。
 
 
6web\PageBase.cs基类
最后谈谈web\PageBase.cs基类吧,所有 Duwamish 7.0 中的所有web页都继承名为 PageBase 的基类,该类实现 Duwamish 7.0 应用程序的 ASP.Net 页中使用的常见属性和方法,这种设计方法值得推荐。
 
Code Snippet分析:
/// <summary>
///     Handles errors that may be encountered when displaying this page.
///     <param name="e">An EventArgs that contains the event data.</param>
/// </summary>
protected override void OnError(EventArgs e)
{
    ApplicationLog.WriteError(ApplicationLog.FormatException(Server.GetLastError(), UNHANDLED_EXCEPTION));
    base.OnError(e);
}
重载OnError方法,使application遭遇到未处理错误的时候,自动调用ApplicationLog.WriteError()来记录错误日志。
 
另外,觉得Duwamishpassword处理有些特别,是以byte形式存放在Database中,避免明文的方式,以提高安全性(将在《Duwamish密码分析篇》进行中分析)
 
 

一、Duwamish 7.0的架构Duwamish 7.0vs.net中微软提供的一个企业级的示例,最近在学设计方面的东西,所以有时间边看边学这个示例。做了一些笔记,和大家一起讨论。    学习Duwamish 7.0,首先要看的当然是它的一个整体的结构式,在msdn自带的帮助文件中,我们看到了它的一个整体的结构,如下图所示: Duwamish 7.0分为四层,分别为:l    Web层相当于是用户界面层,直接与用户交互的web窗体,从源码中我们可以看到,它有以下的一些界面页:页面名称    作用book.aspx    用以显示图书的详细信息的页面default.aspx    默认页,显示当天的精选书categories.aspx    用于分类显示图书的页面,它由两部分组成,上半部分显示当天推荐的该分类的图书信息,下半部分显示该分类的errorpage.aspx    是一个静态页面,显示一成不变的错误信息searchresults.aspx    显示搜索结果页面,用了一个datalist控件显示搜索的结果;不支持分页shoppingcart.aspx    购物车页,用于填写购书的订单,用datagrid控件操作,支持批量修改和更新。不支持删除,设为零时能删除;不用单击update按钮就自动更新了;update按钮用于修改订购书的数量后刷新价格。viewsource.aspx    既然是示例,当然可以看源代码了,这一页是专门用于查看源代码的下面的页面是用于管理用户及用户订单系统,微软专门把它放在secure文件夹下:页面名称    作用account.aspx    新客户注册页及客户修改个人信息页;checkout.aspx    确认购买页面,填写收货人的详细地址和联系方式,填入信用卡的信息,列出购买的清单及总的费用信息。order.aspx    显示用户的订单信息,以供用户打印该订单在Duwamish 7.0中,大量的运用了用户控件,各个用户控件的功能不一,用户控件统一放在modules文件夹下:用户控件名称    作用accountmodule.ascx    对应于account.aspx页面,新客户注册页及客户修改个人信息bannermodule.ascx    每一页都包含有该用户控件,它定义的页面的头部信息,在页面中看到的头上的哪片黑色的区域就是它了,包含一个图片,三个按钮。categoriesmodule.ascx    每一页都包含有该用户控件,它显示了书籍的分类信息。在页面的左边的”Browse Categories”文字开始到” Behind The Scenes”文字结束就是该控件的界面内容了checkoutmodule.ascx    对应于checkout.aspx页,因为checkout.aspx页是一个按步骤操作的页(panel控件控制),每走一页,checkoutmodule.ascx控件中的箭头就往前走或往后退一格。在父页面中通过控制checkoutmodule.ascx控件的Stage属性来控制dailypickmodule.ascx    用于显示推荐的图书信息,在default.aspx页和categories.aspx页中用到searchmodule.ascx    搜索功能控件,每页的搜索功能都由这个控件实现viewsourcemodule.ascx    查看源码功能控件,每页的查看源功能都是由这个用户控件实现所有用户界面层就是上述的页面和用户控件,看起来其实也不多。l    业务外观层什么是业务外观层,这是四层结构里面新增的东西?有什么用呢?现在我也不知道,先让我们看看Duwamish 7.0中业务层中包含一些什么?打开BusinessFacade项目,这里面的东西就是Duwamish 7.0业务外观层了,看看里面有下面的这些文件组成:文件名称    类作用CustomerSystem.cs    CustomerSystem类是客户系统的业务外观层,它为客户子系统提供了一个简单的接口,该类支持远程处理的应用程序中跨应用程序域边界访问。它继承自MarshalByRefObject类。从Duwamish 7.0中提供的visio图上看,CustomerSystem类只有三个方法,分别是:GetCustomerByEmail方法(从email和密码获得客户的信息),UpdateCustomer方法(更新客户的信息,接收一个CustomerData对象),CreateCustomer方法(当然是用于创建一个新的客户了)OrderSystem.cs    OrderSystem类用于处理订单的业务外观,它只有两个方法:GetOrderSummary方法(用于统计订单),AddOrder方法(用于新增一个订单)ProductSystem.cs    ProductSystem类用于处理书的业务外观,它的方法比较多,有五个分别是:GetCategories方法(通过分类的id获得类别自身的信息);GetCategoryItems方法(通过分类的id获得该类下的所有的书的信息);GetDailyPickItems方法(通过分类的id获得该类下的推荐书的信息);GetItemById方法(通过书的id获得有关书的信息);GetSearchItems方法(根据指定的检索字段条件以及书名的关键字查询书的信息)        看了上面业务层的类以后,我们发现所有的业务层类都只有方法,没有属性,我的理解是它是所有与用户界面有关的操作的一些方法的定义。    这两天又到微软中国网站上看看,发现了卢彦写的几篇关于Duwamish 7.0的文章其中的一篇就是有关为什么要加业务外观层的,看了后,才完全理解,下面我们来看看卢彦的这篇文章的片断:    在Web应用程序中,有部分操作只是简单的从数据库根据条件提取数据,不需要经过任何处理,而直接将数据显示到网页上,比如查询某类别的图书列表。而另外一些操作,比如计算定单中图书的总价并根据顾客的级别计算回扣等等,这部分往往有许多不同的功能的类,操作起来也比较复杂。我们可以先想象一下,如果我们采用三层结构,这些商业逻辑一般是会放在中间层,那么对内部的这些大量种类繁多,使用方法也各异的,不同的类的调用任务就完全落到了表示层。这样势必会增加表示层的代码量,将表示层的任务复杂化,和表示层只负责接受用户的输入并返回结果的任务不太相称,并增加了层与层之间的耦合程度。    为了解决这个问题,我们先来看看《设计模式》一文中对Facade模式的描述:意图:    为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。适用性:    当你要为一个复杂子系统提供一个简单接口时。子系统往往因为不断演化而变得越来越复杂。大多数模式使用时都会产生更多更小的类。这使得子系统更具可重用性,也更容易对子系统进行定制,但这也给那些不需要定制子系统的用户带来一些使用上的困难。Facade可以提供一个简单的缺省视图,这一视图对大多数用户来说已经足够,而那些需要更多的可定制性的用户可以越过Facade层。     客户程序与抽象类的实现部分之间存在着很大的依赖性。引入Facade将这个子系统与客户以及其他的子系统分离,可以提高子系统的独立性和可移植性。     当你需要构建一个层次结构的子系统时,使用Facade模式定义子系统中每层的入口点。如果子系统之间是相互依赖的,你可以让它们仅通过Facade进行通讯,从而简化了它们之间的依赖关系。 结构图: 上文提出的这个矛盾,正好和设计模式中Facade模式中所描述的需要解决的问题非常吻合,在《设计模式》中提出的解决的办法就是引入一个Facade对象,让这个Facade来负责管理系统内部类的调用,并为表示层提供了一个单一而简单的接口。这个Facade对象,在我们的Duwamish的设计中,就是BusinessFacade(业务外观)层。l    业务规则层业务规则层包含各种业务规则和逻辑的实现,Duwamish 7.0中业务规则层完成如客户帐户和书籍订单的验证这样的任务。它包含了两个类:文件名称    类作用Customer.cs    它有一个私有的常量REGEXP_ISVALIDEMAIL,用于验证客户的输入的email地址是否正确;insert方法用于验证和新建一条客户记录;update方法用于更新某个客户的信息;GetCustomerByEmail私有方法通过email验证是否已存在该客户的信息;Validate私有方法用于验证customer数据是否正确,它通过调用类内的IsValidEmail(验证email方法)IsValidField(验证字段的内容是否超长字段规定的长度)来验证整个customer对象是否正确Order.cs    私有的常量MINIMUM_SHIPPING_CHARGE,私有的常量STANDARD_ITEM_COUNTCalculateTax方法用于计算税收。CalculateShipping用于计算购物的总价格。InsertOrder方法用于插入一个订单;IsValidField用于验证字段的正确性    从上面的两个类设计来看,业务逻辑层的功能是对业务对象是否符合业务逻辑的验证,无需验证的对象则无需写其业务层,从业务外观层我们看到,CustomerSystem.类对应于Customer类,它对CustomerSystem.提交的CustomeData对象进行验证。Order类则对OrderSystem类提交的OrderData对象进行验证。但是我们看到没有对ProductSystem类的验证的对象,这是因为在Duwamish 7.0中没有提供对product(在这里是指书)对象的更新或新增操作。我想,如果它提供了对书的维护功能的话,它也肯定有这个业务规则对象。    原文请看:http://www.microsoft.com/china/community/TechZone/TechArticle/TechDoc/duwamish.aspl    数据访问层数据访问层负责对业务层提供数据操作,也就是它负责和底层的数据库打交道。业务层或者通用层中所有的对象都通过数据访问层的对象访问数据库。数据访问层中的类是按业务对象来组织的,每个业务对象中包含的数据可能存在不同的几种数据表中,它由数据访问类统一组织成一个概念中的对象,它相当于是一个面向对象的数据库层,负责映射面向对象与关系数据库间的关系。对数据库的所有操作均由存储过程完成,数据层只是在前台调用后台的存储过程。文件名称    类作用Books.cs    Books类有许多的方法,构造函数Books首先创建了一个SqlDataAdapter对象,然后指定了该对象的SqlConnection对象。Books类实现了Idisposable接口,实现的Dispose方法,用于销毁该对象。下面的各个方法都是根据不同的参数获得BookData,包括:GetBooksByCategorId(对应于同名的存储过程,通过类别id获得bookdata数据集对象),GetDailyPickBooksByCategoryId(对应于同名的存储过程,通过类别id获得推荐的bookdata数据集对象),GetBookById(通过书的id取得书的信息),GetBooksByAuthor(通过作者名获得书的信息,可能有N条记录),GetBooksByISBN(通过isbn获得书的信息)GetBooksBySubjectGetBooksByTitle,上述的方法其它都是通过FillBookData(通过传进行存储过程名作参数和参数值执行SqlDataAdapter对象的fill方法填充bookdata对象)方法执行对应的存储过程来获得BookDataCategories.cs    Categories类的方法比较少,除了构造函数和dispose方法外,就只有GetCategories方法(通过分类的id获得该类的父、本、子三级的分类对象)和FillCategoryData私有方法(为GetCategories方法从底层数据库中获取数据到CategoriesData)。Customers.cs    Customers类除了构造函数和dispose方法外,有三个公开的方法,LoadCustomerByEmail方法(调用GetLoadCommand方法,获得sqlcommand对象后,执行GetCustomerByEmail存储过程,获得customerdata对象),UpdateCustomer方法(更新整个的customer对象,在UpdateCustomer存储过程中又调用了UpdateCustomerAddress存储过程来更新Addresses表。它有一个缺点就是每次更都会完全的更新两张表的所有的内容),InsertCustomer(与UpdateCustomer方法类似,它调用InsertCustomerInsertAddress两个存储过程完成两个表的插入工作,唯一不同的插入操作是先插入主表,然后再插入从表。更新是先从表,后主表。),及三个私有的为前三个公开的方法服务的方法。GetLoadCommand方法(生成调用GetCustomerByEmail存储过程的sqlcommand命令返回)GetInsertCommand(生成调用InsertCustomer存储过程的sqlcommand命令返回,它用了sqlparameter对象的sourcecolumn属性映射对dataset的某个对象)GetUpdateCommand(它与GetInsertCommand方法类似)Orders.cs    Orders除了构造函数和dispose方法外,也只有一个公开的方法InsertOrderDetail方法(插入一个订单到数据库,详细的说明看源码注释)及一个私有方法GetInsertCommand(初始化DataAdapter对象的Insert命令参数集)l    通用层映射关系数据库表到实际应用的类(对象)层。相当于是一个面向对象的数据库层,把物理的数据库表的字段映射成业务对象:文件名称    类作用BookData.cs    BookData类继承自dataset类,创建了一个datatable表,用于存储书的数据。支持序列化。(序列化有什么用?它没有声明authors字段,但填充的时却有这个字段?)CategoryData.cs     CategoryData类继承自dataset类,创建了一个datatable表,用于存储书分类的数据。支持序列化。CustomerData.cs    CustomerData类继承自dataset类,创建了一个datatable表,用于存储书的数据。支持序列化。OrderData.cs    OrderData类也继承自dataset类,但它包含了五个表,各个表字段不一样。l    系统架构层文件名称    类作用ApplicationConfiguration    DuwamishConfiguration    太乱了,我把《项目总结》系列和这个打成包,要的,留个email!三、编程技巧学习1.    存储过程技巧1)    输出参数可以当输入参数使用2)    字符串字段的累加的方法我们看看GetBookById存储过程的一段源码:PROCEDURE GetBookById    @BookId INTAS    -- max size = 10 Authors    DECLARE @AuthorList nvarchar(480)    SET NOCOUNT ON    -- initialize @AuthorList    SELECT @AuthorList = ""    -- build list of authors    SELECT @AuthorList = @AuthorList + a.Name + ", "      FROM Books b,            BookAuthor ba,            Authors a     WHERE b.ItemId = @BookId       AND ba.ItemId = b.ItemId       AND a.PKId = ba.AuthorId-- remove last comma SELECT @AuthorList = LEFT(@AuthorList,LEN(@AuthorList) - 1)      把这段单独拷出来,在查询分析器运行,我们发现这段是用来取某本书的作者的列表,一本书可能有多个作者,SELECT @AuthorList = @AuthorList + a.Name + ", "      FROM Books b,            BookAuthor ba,            Authors a     WHERE b.ItemId = @BookId       AND ba.ItemId = b.ItemId                       AND a.PKId = ba.AuthorId    就是把书的作者名一个个取出来,累加到@AuthorList变量中,各个作者用逗号隔开,最后一句SELECT @AuthorList = LEFT(@AuthorList,LEN(@AuthorList) - 1)把最后一个作者后的逗号去掉。3)    存储过程参数与dataset中字段的映射在Customers类中的GetInsertCommand方法中,我们看到了下面的代码:sqlParams[PKID_PARM].SourceColumn = CustomerData.PKID_FIELD;                    sqlParams[PKID_PARM].Direction = ParameterDirection.Output; sqlParams[EMAIL_PARM].SourceColumn = CustomerData.EMAIL_FIELD;        它运用了sqlparameter对象的SourceColumn属性,该属性用于指定sqlparameter对象的值与dataset中字段的映射。它是双向,即是输入值,也是输出值。sqlParams[EMAIL_PARM].SourceColumn = CustomerData.EMAIL_FIELD;这一句表示把CustomerData(dataset对象)EMAIL_FIELD字段值映射成sqlParams[EMAIL_PARM]的参数值。4)    2.    Web 编程技巧1)    运用ado.net中的dataview对已存在结果集进行再查询在cart类的AddItem方法中我们可看到源码:public void AddItem(int itemId, String itemDescription, Decimal itemPrice)        {            DataTable itemTable = OrderItems;            DataView itemSource = new DataView(itemTable);                    //search for item, check to see if the item has already been ordered            //通过itemid查找item,检查是否已预定该item,利用DataViewRowFilter属性,设置其过滤条件。            //接下来用DataViewcount属性执行查询并返回满足条件的记录数            itemSource.RowFilter = "ItemNumber = " + itemId.ToString();                        //如果已经订了该书,增加数量            if (itemSource.Count > 0)            {                DataRowView sourceRow = itemSource[0];                short count = (short)(sourceRow[OrderData.QUANTITY_FIELD]);                //maximum allowed for any specific item is 50                //每种书最多允许订50本                if (count < 50)                {                    //bump the quantity by one                    //订购书本的数量加一,更新orderdata对象(数量,总价)                    count += 1;                    sourceRow[OrderData.QUANTITY_FIELD] = count;  sourceRow[OrderData.EXTENDED_FIELD] = (Decimal)sourceRow[OrderData.PRICE_FIELD] * count;                }            }            //先前没有订该书            else            {                        //It's a new item                //orderdata里面新增一条记录                DataRow itemRow = itemTable.NewRow();                itemRow[OrderData.ITEM_NUMBER_FIELD] = itemId;                itemRow[OrderData.QUANTITY_FIELD] = 1;                itemRow[OrderData.DESCRIPTION_FIELD] = itemDescription;                itemRow[OrderData.PRICE_FIELD] = itemPrice;                itemRow[OrderData.EXTENDED_FIELD] = itemPrice;                        //Add it to the table                itemTable.Rows.Add(itemRow);}}3.系统配置技巧4.    其它1)    对象的序列化在cart类中,我们可以看到该类实现了Iserializable接口,首先我们了解一下什么是序列化,我以前也没有接触过,所以上网查了一下,在微软的网站中找到了这篇文章---.NET 中的对象序列化(原文网址:http://www.microsoft.com/china/msdn/library/dndotnet/html/objserializ.asp)。为什么要使用序列化?最重要的两个原因是:将对象的状态保存在存储媒体中以便可以在以后重新创建出完全相同的副本;按值将对象从一个应用程序域发送至另一个应用程序域。例如,序列化可用于在 ASP.NET 中保存会话状态,以及将对象复制到 Windows 窗体的剪贴板中。它还可用于按值将对象从一个应用程序域远程传递至另一个应用程序域。序列化是指将对象实例的状态存储到存储媒体(例如说硬盘)的过程。在此过程中,先将对象的公共字段和私有字段以及类的名称(包括类所在的程序集)转换为字节流,然后再把字节流写入数据流。在随后对对象进行反序列化时,将创建出与原对象完全相同的副本。要实现 ISerializable,需要实现 GetObjectData 方法以及一个特殊的构造函数,在反序列化对象时要用到此构造函数。我们看看在眼里cart类的持殊的构造函数:private Cart(SerializationInfo info, StreamingContext context)        {            try            {                cartOrderData = (Common.Data.OrderData)info.GetValue(KEY_ORDERDATA, typeof(Common.Data.OrderData));            }            catch            {                // Leave cartOrderData null if it hasn't been serialized} }              这个构造函数在反序列化的时候被调用,用于从磁盘中获得OrderData对象。再看看GetObjectData 方法的代码:void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)        {            if (cartOrderData != null)            {                info.AddValue(KEY_ORDERDATA, cartOrderData);            }        }该方法把cartOrderData对象序列化,也就相同于把它存到磁盘了。在反序列化,也就是调用上面的那个构造函数,再把它从磁盘中取出来.