<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_liulun</title><subtitle type="text">专注！坚持！</subtitle><id>http://feed.cnblogs.com/blog/u/32486/rss</id><updated>2012-02-05T04:16:25Z</updated><author><name>liulun</name><uri>http://www.cnblogs.com/liulun/</uri></author><generator>CNBlogs BlogServer</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/liulun/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/32486/rss"/><entry><id>http://www.cnblogs.com/liulun/archive/2012/02/05/2338892.html</id><title type="text">【翻译】在没有安装ASP.NET MVC3的服务器上运行ASP.NET MVC3的程序-scottgu</title><summary type="text">原文地址： http://weblogs.asp.net/scottgu/archive/2011/01/18/running-an-asp-net-mvc-3-app-on-a-web-server-that-doesn-t-have-asp-net-mvc-3-installed.aspx 为了更符合中文阅读习惯，我对原文做了小幅度修改 最近我们发布了一些新的Web产品 - 包括ASP.N...</summary><published>2012-02-05T04:16:00Z</published><updated>2012-02-05T04:16:00Z</updated><author><name>liulun</name><uri>http://www.cnblogs.com/liulun/</uri></author><link rel="alternate" href="http://www.cnblogs.com/liulun/archive/2012/02/05/2338892.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/liulun/archive/2012/02/05/2338892.html"/><content type="html">&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt; &lt;p&gt;原文地址：&lt;/p&gt; &lt;p&gt;&lt;a title="http://weblogs.asp.net/scottgu/archive/2011/01/18/running-an-asp-net-mvc-3-app-on-a-web-server-that-doesn-t-have-asp-net-mvc-3-installed.aspx" href="http://weblogs.asp.net/scottgu/archive/2011/01/18/running-an-asp-net-mvc-3-app-on-a-web-server-that-doesn-t-have-asp-net-mvc-3-installed.aspx"&gt;http://weblogs.asp.net/scottgu/archive/2011/01/18/running-an-asp-net-mvc-3-app-on-a-web-server-that-doesn-t-have-asp-net-mvc-3-installed.aspx&lt;/a&gt;&lt;/p&gt; &lt;p&gt;为了更符合中文阅读习惯，我对原文做了小幅度修改&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;最近我们发布了一些新的&lt;a href="http://weblogs.asp.net/scottgu/archive/2011/01/13/announcing-release-of-asp-net-mvc-3-iis-express-sql-ce-4-web-farm-framework-orchard-webmatrix.aspx"&gt;Web产品&lt;/a&gt; - 包括&lt;a href="http://weblogs.asp.net/scottgu/archive/2011/01/13/announcing-release-of-asp-net-mvc-3-iis-express-sql-ce-4-web-farm-framework-orchard-webmatrix.aspx"&gt;ASP.NET MVC 3&lt;/a&gt;。至今为止，我们已经获得了大量的反馈。&lt;/p&gt; &lt;p&gt;有几个朋友在问我一个问题：“我的网站托管服务提供商目前还不支持ASP.NET MVC 3 - 你知道他们将来什么时候会安装吗？”&lt;/p&gt; &lt;p&gt;好消息是，您不必等他们在Web服务器上安装ASP.NET MVC3。&lt;/p&gt; &lt;p&gt;只要您的网站托管服务提供商支持.NET 4，那么您现在就可以构建和部署ASP.NET MVC3应用程序了 &lt;/p&gt; &lt;p&gt;- 不用托管供应商做任何事。&lt;/p&gt; &lt;p&gt;下面的文章介绍如何启用此功能。&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;font color="#ff0000"&gt;&lt;strong&gt;一些背景：&lt;/strong&gt;&lt;br&gt;&lt;/font&gt;我们支持两种方式使您可以使用一台机器上的ASP.NET MVC3组件：&lt;br&gt;1，在一台机器上，将ASP.NET MVC 3组件安装在一个集中的地方，WEB项目在那里引用这些组件&lt;/p&gt; &lt;p&gt;2，把ASP.NET MVC 3的组件复制到您的Web项目的\bin文件夹下，WEB项目在那里引用这些组件&lt;/p&gt; &lt;p&gt;第一种方法是我们使用Visual Studio中使用的默认方法，&lt;/p&gt; &lt;p&gt;这使得我们可以更容易为ASP.NET MVC 3提供升级服务（当发现BUG的时候）。&lt;/p&gt; &lt;p&gt;第二种方法也是得到了完全支持，没有在服务器上安装ASP.NET MVC3，也可以使用它。&lt;/p&gt; &lt;p&gt;你只要把ASP.NET MVC的组件放在你的WEB程序的bin目录中，然后把整个Web程序拷贝到FTP（WEB服务器）上，它就可以工作了。&lt;/p&gt; &lt;p&gt;如果您的网站托管服务提供商还没有在他们的服务器上安装ASP.NET MVC 3，那么您应该使用第二种方法。&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;font color="#ff0000"&gt;&lt;strong&gt;方法1：基于GAC引用ASP.NET MVC组件&lt;/strong&gt;&lt;br&gt;&lt;/font&gt;当您在计算机上安装ASP.NET MVC 3的时候，&lt;/p&gt; &lt;p&gt;一些组件会自动注册到&lt;a href="http://en.wikipedia.org/wiki/Global_Assembly_Cache"&gt;GAC&lt;/a&gt;中（全局程序集缓存）。&lt;/p&gt; &lt;p&gt;GAC提供一个集中的地方供安装和升级（通过Windows更新）.NET程序集。&lt;/p&gt; &lt;p&gt;因此ASP.NET MVC3项目默认在这里引用程序集。&lt;/p&gt; &lt;p&gt;如果你复制一个普通的ASP.NET MVC 3项目（使用默认的方法引用ASP.NET MVC3的程序集）&lt;/p&gt; &lt;p&gt;到一台没有安装ASP.NET MVC3的机器上，&lt;/p&gt; &lt;p&gt;当你运行应用程序时，&lt;/p&gt; &lt;p&gt;会看到一个类似的错误信息：&lt;/p&gt; &lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/scottgu/image_64EB2E92.png"&gt;&lt;img title="image" border="0" alt="image" src="http://weblogs.asp.net/blogs/scottgu/image_thumb_2A2385BC.png" width="735" height="301"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;上述错误表示，&lt;/p&gt; &lt;p&gt;至少有一个运行ASP.NET MVC 3所需的程序集在GAC中找不到。&lt;/p&gt; &lt;p&gt;在机器上安装ASP.NET MVC 3就能解决这个问题，&lt;/p&gt; &lt;p&gt;让您的应用程序正常运行。&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;font color="#ff0000"&gt;&lt;strong&gt;方法2：基于\ Bin目录中引用ASP.NET MVC组件&lt;/strong&gt;&lt;/font&gt;&lt;br&gt;您的项目可以使用另一种方法&lt;/p&gt; &lt;p&gt;在您的Web应用程序的\bin目录中分发和引用的ASP.NET MVC3的程序集。&lt;/p&gt; &lt;p&gt;这种方法的好处是，你并不需要在一台机器上安装ASP.NET MVC3，以运行基于ASP.NET MVC3 Web应用程序。&lt;/p&gt; &lt;p&gt;相反，你只要复制你的web应用程序（在bin目录中包含MVC3的组件）到 .NET4服务器上，它就会运行。&lt;/p&gt; &lt;p&gt;这种方法是“完全信任”，“中等信任”的情景 （&lt;em&gt;译注：我也不知道是什么意思&lt;/em&gt;）&lt;/p&gt; &lt;p&gt;这意味着它甚至可以和低成本共享主机供应商共事。&lt;/p&gt; &lt;p&gt;无需托管服务提供商另外注册/安装/操作需要。&lt;/p&gt; &lt;p&gt;使您的Web项目包含ASP.NET MVC3程序集“bin部署”是非常简单的，&lt;/p&gt; &lt;p&gt;只需2分钟左右。下面是需要遵循的步骤：&lt;/p&gt; &lt;p&gt;&lt;a href="http://drew-prog.blogspot.com/2011/01/how-to-deploy-aspnet-mvc-3-app-to-web.html"&gt;Steps to Deploy an ASP.NET MVC 3 Application to a Web Hosting Provider with \Bin deployment&lt;/a&gt;&lt;/p&gt; &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt; &lt;p&gt;译注：这个链接好像打不开，笔者提供一个方法：&lt;/p&gt; &lt;p&gt;选中ASP.NET MVC引用的程序集，然后查看属性，把“复制到本地”修改为true&lt;/p&gt; &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/liulun/201202/201202051216232315.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/liulun/201202/201202051216242348.png" width="350" height="517"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;asp.net mvc3需要的程序集有&lt;/p&gt; &lt;ul&gt; &lt;li&gt;System.Web.Mvc &lt;li&gt;Microsoft.Web.Infrastructure  &lt;li&gt;System.Web.Razor  &lt;li&gt;System.Web.WebPages  &lt;li&gt;System.Web.WebPages.Razor &lt;/li&gt;&lt;/ul&gt;&lt;/blockquote&gt; &lt;p&gt;&lt;br&gt;一旦配置\BIN部署后，&lt;/p&gt; &lt;p&gt;您使用ASP.NET MVC 3构建的应用程序将在任何安装.NET4的Web服务器上工作。&lt;/p&gt; &lt;p&gt;只需复制到Web服务器，它就会运行。&lt;/p&gt; &lt;p&gt;即使是低成本共享托管账户，你也无需托管服务供应商做任何事。&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;font color="#ff0000"&gt;找一个ASP.NET MVC 3网站托管服务提供商&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;您可以浏览&lt;a href="http://www.microsoft.com/web/hosting/home"&gt;Windows Web Hosting Gallery&lt;/a&gt;（Windows网站托管库）找到所有支持托管服务提供商：&lt;br&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/liulun/201202/201202051216243253.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/liulun/201202/201202051216252480.png" width="508" height="424"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Windows网站托管库允许您通过不同国家和服务水平来筛选/浏览托管服务。&lt;/p&gt; &lt;p&gt;它还能让您轻松过滤“共享主机”，“虚拟主机”和“专用主机”供应商。&lt;/p&gt; &lt;p&gt;“共享主机”是指在你没有管理员权限的远程服务器上，提供单一的Web服务器。&lt;br&gt;“虚拟主机”供应商在一个远程服务器上提供给你虚拟机 - 通常通过操作系统管理权限和管理的远程终端服务器来访问。&lt;/p&gt; &lt;p&gt;“专用主机”供应商提供您一个完整的物理服务器，通常也提供操作系统的管理员权限和远程终端支持。&lt;/p&gt; &lt;p&gt;基于Windows的网络托管的价格现在是非常符合成本效益的，&lt;/p&gt; &lt;p&gt;共享主机低至$2.75/月，虚拟主机提供的报价$23/月。&lt;/p&gt; &lt;p&gt;上述主机都能通过使用\ bin部署方法来运行ASP.NET MVC 3。&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;font color="#ff0000"&gt;摘要&lt;/font&gt;&lt;/strong&gt;&lt;br&gt;ASP.NET MVC 3的应用程序可以部署到任何拥有.NET4的Web服务器，&lt;/p&gt; &lt;p&gt;而不必等待托管服务提供商来安装ASP.NET MVC 3组件。&lt;/p&gt; &lt;p&gt;通过\ bin部署ASP.NET MVC3程序集，&lt;/p&gt; &lt;p&gt;只需使用上面的步骤就可转换您的项目，&lt;/p&gt; &lt;p&gt;那么你就可以复制你的应用程序到任何ASP.NET4服务器上。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/liulun/aggbug/2338892.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/liulun/archive/2012/02/05/2338892.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/liulun/archive/2012/02/03/2337163.html</id><title type="text">Silverlight企业应用框架设计【六】自定义系统菜单（使用自己的DataForm）</title><summary type="text">索引SilverLight企业应用框架设计【五】客户端调用服务端（使用JSON传递数据，自己实现RESTful Web服务）SilverLight企业应用框架设计【四】实体层设计+为客户端动态生成服务代理(自己实现RiaService)SilverLight企业应用框架设计【三】服务端设计SilverLight企业应用框架设计【二】框架画面SilverLight企业应用框架设计【一】整体说明首先我们设计的窗体如下xaml代码如下：&amp;lt;location:BasePage x:Class=&amp;quot;RTMDemo.Frame.Pages.Sys.MenuLE&amp;quot; xmlns=&amp;quo</summary><published>2012-02-03T07:25:00Z</published><updated>2012-02-03T07:25:00Z</updated><author><name>liulun</name><uri>http://www.cnblogs.com/liulun/</uri></author><link rel="alternate" href="http://www.cnblogs.com/liulun/archive/2012/02/03/2337163.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/liulun/archive/2012/02/03/2337163.html"/><content type="html">&lt;p&gt;索引&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://www.cnblogs.com/liulun/archive/2012/02/02/2336182.html"&gt;SilverLight企业应用框架设计【五】客户端调用服务端（使用JSON传递数据，自己实现RESTful Web服务）&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://www.cnblogs.com/liulun/archive/2012/02/01/2335138.html"&gt;SilverLight企业应用框架设计【四】实体层设计+为客户端动态生成服务代理(自己实现RiaService)&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://www.cnblogs.com/liulun/archive/2012/01/05/2313674.html"&gt;SilverLight企业应用框架设计【三】服务端设计&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://www.cnblogs.com/liulun/archive/2012/01/04/2312482.html"&gt;SilverLight企业应用框架设计【二】框架画面&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://www.cnblogs.com/liulun/archive/2012/01/03/2311072.html"&gt;SilverLight企业应用框架设计【一】整体说明&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;首先我们设计的窗体如下&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/liulun/201202/201202031525276662.png"&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" title="image" src="http://images.cnblogs.com/cnblogs_com/liulun/201202/201202031525283140.png" alt="image" width="406" height="364" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;xaml代码如下：&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b;"&gt;&#xD;
&lt;pre&gt;&amp;lt;location:BasePage x:Class="RTMDemo.Frame.Pages.Sys.MenuLE" &#xD;
           xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" &#xD;
           xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" &#xD;
           xmlns:d="http://schemas.microsoft.com/expression/blend/2008"&#xD;
           xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"&#xD;
           mc:Ignorable="d"&#xD;
           xmlns:dataForm="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.DataForm.Toolkit"&#xD;
           xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"&#xD;
                   xmlns:toolkit="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Input.Toolkit"&#xD;
           xmlns:location="clr-namespace:RTMDemo.Frame.Pages"&#xD;
           xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"&#xD;
           d:DesignWidth="640" d:DesignHeight="580" xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"&amp;gt;&#xD;
    &amp;lt;Grid x:Name="LayoutRoot" Loaded="LayoutRoot_Loaded"&amp;gt;&#xD;
        &amp;lt;Grid.ColumnDefinitions&amp;gt;&#xD;
            &amp;lt;ColumnDefinition x:Name="CDL" Width="200"/&amp;gt;&#xD;
            &amp;lt;ColumnDefinition Width="5"/&amp;gt;&#xD;
            &amp;lt;ColumnDefinition Width="*"/&amp;gt;&#xD;
        &amp;lt;/Grid.ColumnDefinitions&amp;gt;&#xD;
        &amp;lt;controls:GridSplitter Grid.Column="1"  HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/&amp;gt;&#xD;
        &amp;lt;ScrollViewer Grid.Row="0" Grid.Column="0" &#xD;
                      Width="{Binding ElementName=CDL,Path=Width}" &#xD;
                      HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"&amp;gt;&#xD;
            &amp;lt;sdk:TreeView BorderThickness="0" Name="MenuTV" SelectedItemChanged="MenuTV_SelectedItemChanged"&amp;gt;&#xD;
            &amp;lt;/sdk:TreeView&amp;gt;&#xD;
        &amp;lt;/ScrollViewer&amp;gt;&#xD;
        &amp;lt;Grid x:Name="MenuFormG" Grid.Column="2"&amp;gt;&#xD;
            &amp;lt;Grid.ColumnDefinitions&amp;gt;&#xD;
                &amp;lt;ColumnDefinition Width="60"&amp;gt;&amp;lt;/ColumnDefinition&amp;gt;&#xD;
                &amp;lt;ColumnDefinition Width="8"&amp;gt;&amp;lt;/ColumnDefinition&amp;gt;&#xD;
                &amp;lt;ColumnDefinition Width="*"&amp;gt;&amp;lt;/ColumnDefinition&amp;gt;&#xD;
            &amp;lt;/Grid.ColumnDefinitions&amp;gt;&#xD;
            &amp;lt;Grid.RowDefinitions&amp;gt;&#xD;
                &amp;lt;RowDefinition Height="32"&amp;gt;&amp;lt;/RowDefinition&amp;gt;&#xD;
                &amp;lt;RowDefinition Height="32"&amp;gt;&amp;lt;/RowDefinition&amp;gt;&#xD;
                &amp;lt;RowDefinition Height="32"&amp;gt;&amp;lt;/RowDefinition&amp;gt;&#xD;
                &amp;lt;RowDefinition Height="32"&amp;gt;&amp;lt;/RowDefinition&amp;gt;&#xD;
                &amp;lt;RowDefinition Height="*"&amp;gt;&amp;lt;/RowDefinition&amp;gt;&#xD;
                &amp;lt;RowDefinition Height="32"&amp;gt;&amp;lt;/RowDefinition&amp;gt;&#xD;
            &amp;lt;/Grid.RowDefinitions&amp;gt;&#xD;
            &amp;lt;sdk:Label Target="{Binding ElementName=MenuNameTB}"&#xD;
                       VerticalAlignment="Center" HorizontalAlignment="Right"&#xD;
                       &amp;gt;&amp;lt;/sdk:Label&amp;gt;&#xD;
            &amp;lt;TextBox Name="MenuNameTB" Grid.Column="2" Grid.Row="0" HorizontalAlignment="Left" Width="300" &#xD;
                            VerticalAlignment="Center" Height="22" Text="{Binding MenuName, Mode=TwoWay                &#xD;
                    ,NotifyOnValidationError=True,ValidatesOnExceptions=True}"&amp;gt;&#xD;
            &amp;lt;/TextBox&amp;gt;&#xD;
&#xD;
            &amp;lt;sdk:Label Grid.Row="1" Target="{Binding ElementName=MenuOrderTB}"&#xD;
                       VerticalAlignment="Center" HorizontalAlignment="Right"&#xD;
                       &amp;gt;&amp;lt;/sdk:Label&amp;gt;&#xD;
            &amp;lt;TextBox Name="MenuOrderTB" Grid.Column="2" Grid.Row="1" &#xD;
                     HorizontalAlignment="Left" Width="100" &#xD;
                        VerticalAlignment="Center" Height="22"     &#xD;
                        Text="{Binding OrderNum,Mode=TwoWay&#xD;
                    ,NotifyOnValidationError=True,ValidatesOnExceptions=True}"&amp;gt;&amp;lt;/TextBox&amp;gt;&#xD;
&#xD;
&#xD;
            &amp;lt;sdk:Label Grid.Row="2" Content="菜单路径"&#xD;
                       VerticalAlignment="Center" HorizontalAlignment="Right"&#xD;
                       &amp;gt;&amp;lt;/sdk:Label&amp;gt;&#xD;
            &amp;lt;ComboBox x:Name="MenuUrlCB" Height="22" Width="300"&#xD;
                      SelectedValue="{Binding Url,Mode=TwoWay}"&#xD;
                    Grid.Column="2" Grid.Row="2" HorizontalAlignment="Left"&amp;gt;&amp;lt;/ComboBox&amp;gt;&#xD;
&#xD;
            &amp;lt;TextBlock  Grid.Row="3" Text="父级菜单" VerticalAlignment="Center" HorizontalAlignment="Right"&amp;gt;&amp;lt;/TextBlock&amp;gt;&#xD;
            &amp;lt;ComboBox Grid.Column="2" Grid.Row="3" DisplayMemberPath="MenuName" x:Name="TMenuCB"&#xD;
                      Height="22" Width="100"&#xD;
                    HorizontalAlignment="Left"&amp;gt;&#xD;
            &amp;lt;/ComboBox&amp;gt;&#xD;
&#xD;
            &amp;lt;sdk:Label Grid.Row="4" Target="{Binding ElementName=HelpTB}"&#xD;
                       VerticalAlignment="Center" HorizontalAlignment="Right"&#xD;
                       &amp;gt;&amp;lt;/sdk:Label&amp;gt;&#xD;
            &amp;lt;TextBox Grid.Column="2" Grid.Row="4" x:Name="HelpTB"&#xD;
                            AcceptsReturn="True"&#xD;
                            TextWrapping="Wrap"&#xD;
                            VerticalScrollBarVisibility="Auto"&#xD;
                        Text="{Binding MenuDes,Mode=TwoWay&#xD;
                    ,NotifyOnValidationError=True,ValidatesOnExceptions=True}"&amp;gt;&amp;lt;/TextBox&amp;gt;&#xD;
&#xD;
            &amp;lt;StackPanel Grid.Column="2" Grid.Row="111"  Orientation="Horizontal"&amp;gt;&#xD;
                &amp;lt;Button x:Name="AddBTN" Width="100" Height="22"  Margin="0 0 10 0" Content="增加" Click="AddBTN_Click"&amp;gt;&amp;lt;/Button&amp;gt;&#xD;
                &amp;lt;Button x:Name="EditBTN" Width="100" Height="22" Margin="0 0 10 0"  Content="修改" Click="EditBTN_Click"&amp;gt;&amp;lt;/Button&amp;gt;&#xD;
                &amp;lt;Button x:Name="DelBTN" Width="100" Height="22" Margin="0 0 10 0"  Content="删除" Click="DelBTN_Click"&amp;gt;&amp;lt;/Button&amp;gt;&#xD;
            &amp;lt;/StackPanel&amp;gt;&#xD;
        &amp;lt;/Grid&amp;gt;&#xD;
    &amp;lt;/Grid&amp;gt;&#xD;
&amp;lt;/location:BasePage&amp;gt;&#xD;
&lt;/pre&gt;&#xD;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;&#xD;
&lt;/fieldset&gt;&#xD;
&lt;p&gt;需要说明的：&lt;/p&gt;&#xD;
&lt;p&gt;1.&lt;/p&gt;&#xD;
&lt;p&gt;所有的业务窗体都继承自BasePage类&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/liulun/201202/20120203152528142.png"&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" title="image" src="http://images.cnblogs.com/cnblogs_com/liulun/201202/201202031525298256.png" alt="image" width="250" height="102" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;这也是为什么xaml代码的开始处是&amp;lt;location:BasePage&amp;hellip;.&lt;/p&gt;&#xD;
&lt;p&gt;2.&lt;/p&gt;&#xD;
&lt;p&gt;由于左侧的树控件和右侧的Grid控件中间&lt;/p&gt;&#xD;
&lt;p&gt;有个GridSplitter控件&lt;/p&gt;&#xD;
&lt;p&gt;所以可以自由的拖动GridSplitter控件以变化左右两侧控件的大小&lt;/p&gt;&#xD;
&lt;p&gt;树控件我们暂且不提（没有什么特殊的地方）&lt;/p&gt;&#xD;
&lt;p&gt;-------------------------&lt;/p&gt;&#xD;
&lt;p&gt;在加载页面的Loaded事件中执行了如下代码&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b;"&gt;&#xD;
&lt;pre&gt;private void LayoutRoot_Loaded(object sender, RoutedEventArgs e)&#xD;
        {            &#xD;
            if (IsLoaded)&#xD;
            {&#xD;
                return;&#xD;
            }&#xD;
            InitMenuTree();&#xD;
            InitTypeCB();&#xD;
        }&lt;/pre&gt;&#xD;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;&#xD;
&lt;/fieldset&gt;&#xD;
&lt;p&gt;其中IsLoaded属性是基类BasePage的属性&lt;/p&gt;&#xD;
&lt;p&gt;代码如下&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b;"&gt;&#xD;
&lt;pre&gt;protected bool IsLoaded = false;&#xD;
        public BasePage()&#xD;
        {&#xD;
            this.Loaded += new RoutedEventHandler(BasePage_Loaded);&#xD;
        }&#xD;
        void BasePage_Loaded(object sender, RoutedEventArgs e)&#xD;
        {&#xD;
            IsLoaded = true;&#xD;
        }&lt;/pre&gt;&#xD;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;&#xD;
&lt;/fieldset&gt;&#xD;
&lt;p&gt;这样做就是为了避免重复执行InitMenuTree和InitTypeCB两个方法的代码&lt;/p&gt;&#xD;
&lt;p&gt;（tab页面切换会触发Loaded事件）&lt;/p&gt;&#xD;
&lt;p&gt;------------------------------------&lt;/p&gt;&#xD;
&lt;p&gt;先来看InitMenuTree的代码&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b;"&gt;&#xD;
&lt;pre&gt;void InitMenuTree()&#xD;
        {&#xD;
            var tMenu = Common.ViewUtility.AllMenu&#xD;
                    .Where(m =&amp;gt; m.ParentId == Guid.Empty)&#xD;
                    .OrderBy(m=&amp;gt;m.OrderNum);&#xD;
            InitParentMenu(tMenu);&#xD;
            foreach (var tm in tMenu)&#xD;
            {&#xD;
                var ttvi = new TreeViewItem();&#xD;
                ttvi.Header = tm.MenuName;&#xD;
                ttvi.DataContext = tm;&#xD;
                if (MenuTV.Items.Count &amp;lt; 1)&#xD;
                {&#xD;
                    MenuFormG.DataContext = tm;&#xD;
                    ttvi.IsSelected = true;&#xD;
                }&#xD;
                ttvi.IsExpanded = true;&#xD;
                MenuTV.Items.Add(ttvi);&#xD;
                var sMenu = Common.ViewUtility.AllMenu&#xD;
                        .Where(m =&amp;gt; m.ParentId == tm.Id)&#xD;
                        .OrderBy(m =&amp;gt; m.OrderNum);&#xD;
                foreach (var sm in sMenu)&#xD;
                {&#xD;
                    var stvi = new TreeViewItem();&#xD;
                    stvi.Header = sm.MenuName;&#xD;
                    stvi.DataContext = sm;&#xD;
                    ttvi.Items.Add(stvi);                    &#xD;
                }&#xD;
            }&#xD;
        }&lt;/pre&gt;&#xD;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;&#xD;
&lt;/fieldset&gt;&#xD;
&lt;p&gt;笔者并没有使用数据绑定的形式给控件赋值&lt;/p&gt;&#xD;
&lt;p&gt;而是直接创建了树控件的子控件来赋值的（这与我们的数据结构有关,这样做更简便一些）&lt;/p&gt;&#xD;
&lt;p&gt;MenuM类型并不是一个自引用的类型（没有记录ParentMenu只记录了ParentId）&lt;/p&gt;&#xD;
&lt;p&gt;其中InitParentMenu是初始化下拉框的函数（修改子菜单的父级菜单时用到，这里就不多说了）&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b;"&gt;&#xD;
&lt;pre&gt;/// &amp;lt;summary&amp;gt;&#xD;
        /// 构造父级菜单的combo box&#xD;
        /// &amp;lt;/summary&amp;gt;&#xD;
        /// &amp;lt;param name="tMenu"&amp;gt;&amp;lt;/param&amp;gt;&#xD;
        void InitParentMenu(IEnumerable&amp;lt;MenuM&amp;gt; tMenu)&#xD;
        {&#xD;
            var rs = tMenu.ToList();&#xD;
            var TM = new MenuM();&#xD;
            TM.MenuName = "请选择";&#xD;
            TM.Id = Guid.Empty;&#xD;
            rs.Insert(0, TM);&#xD;
            TMenuCB.ItemsSource = rs;&#xD;
            TMenuCB.SelectedIndex = 0;&#xD;
        }&lt;/pre&gt;&#xD;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;&#xD;
&lt;/fieldset&gt;&#xD;
&lt;p&gt;-----------------------------------------------&lt;/p&gt;&#xD;
&lt;p&gt;InitTypeCB是构造可以使用的菜单路径（下拉框）的函数&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b;"&gt;&#xD;
&lt;pre&gt;void InitTypeCB()&#xD;
        {&#xD;
            var tys = Application.Current.GetType().Assembly.GetTypes().ToList();&#xD;
            var results = tys.Where(m =&amp;gt;  m.IsPublic &#xD;
                                            &amp;amp;&amp;amp; m.FullName.StartsWith("RTMDemo.Frame.Pages")&#xD;
                                            &amp;amp;&amp;amp; !m.FullName.EndsWith(".BasePage"))&#xD;
                             .Select(m=&amp;gt;m.FullName.TrimStart("RTMDemo.Frame.".ToArray()))&#xD;
                             .ToList();&#xD;
            results.Insert(0,"请选择");&#xD;
            MenuUrlCB.ItemsSource = results;&#xD;
            MenuUrlCB.UpdateLayout();&#xD;
            MenuUrlCB.SelectedIndex = 0;&#xD;
        }&lt;/pre&gt;&#xD;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;&#xD;
&lt;/fieldset&gt;&#xD;
&lt;p&gt;此函数反射出了所有业务窗体的类名，并赋值给了一个ComboBox,以供选择&lt;/p&gt;&#xD;
&lt;p&gt;---------------------------------------------------------------&lt;/p&gt;&#xD;
&lt;p&gt;当选中菜单树中的某一项时执行如下事件&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b;"&gt;&#xD;
&lt;pre&gt;private void MenuTV_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs&amp;lt;object&amp;gt; e)&#xD;
        {&#xD;
            var item = MenuTV.SelectedItem as TreeViewItem;&#xD;
            var menuObj = item.DataContext as MenuM;&#xD;
            var fobj = Common.Utility.DeepCopy(menuObj);&#xD;
            MenuFormG.DataContext = fobj;&#xD;
            var parent = Common.ViewUtility.AllMenu&#xD;
                       .Where(m =&amp;gt; m.Id == menuObj.ParentId)&#xD;
                       .FirstOrDefault();&#xD;
            TMenuCB.SelectedItem = (parent == null ? TMenuCB.Items.FirstOrDefault() : parent);&#xD;
            MenuUrlCB.SelectedItem = (string.IsNullOrEmpty(menuObj.Url) ? "请选择" : menuObj.Url);&#xD;
        }&lt;/pre&gt;&#xD;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;&#xD;
&lt;/fieldset&gt;&#xD;
&lt;p&gt;因为MenuFormG内的数据绑定元素基本上都是使用的双向绑定（更改会直接反应在实体上）&lt;/p&gt;&#xD;
&lt;p&gt;所以我们深拷贝了一个实体提供给表单（这样就不会影响现有实体的数据）&lt;/p&gt;&#xD;
&lt;p&gt;技巧：深拷贝其实就是执行了一次序列化和反序列化的过程&lt;/p&gt;&#xD;
&lt;p&gt;代码如下:&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b;"&gt;&#xD;
&lt;pre&gt;public static object DeepCopy(object tar)&#xD;
        {&#xD;
            MemoryStream ms = new MemoryStream();&#xD;
            var jsonSerializer = new DataContractJsonSerializer(tar.GetType());&#xD;
            jsonSerializer.WriteObject(ms, tar);&#xD;
            var result = jsonSerializer.ReadObject(ms);&#xD;
            return result;&#xD;
        }&lt;/pre&gt;&#xD;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;&#xD;
&lt;/fieldset&gt;&#xD;
&lt;p&gt;------------------------------------------------------&lt;/p&gt;&#xD;
&lt;p&gt;下面我们来看一下增加一个菜单的方法&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b;"&gt;&#xD;
&lt;pre&gt;private void AddBTN_Click(object sender, RoutedEventArgs e)&#xD;
        {&#xD;
            var obj = MenuFormG.DataContext as MenuM;&#xD;
            if (FormHasError(MenuFormG))&#xD;
            {&#xD;
                Common.ViewUtility.Alert("数据有误不能提交");&#xD;
                return;&#xD;
            }&#xD;
            var ms = new MenuService();&#xD;
            obj.Id = Guid.NewGuid();&#xD;
            obj.ParentId = (TMenuCB.SelectedItem as MenuM).Id;&#xD;
            ms.Completed += new ServiceEventHandler((o, se) =&amp;gt;&#xD;
            {&#xD;
                Common.ViewUtility.Alert("增加成功");&#xD;
                Common.ViewUtility.AllMenu.Add(obj);&#xD;
                Reload();&#xD;
            });&#xD;
            ms.AddMenu(obj);&#xD;
            &#xD;
        }&lt;/pre&gt;&#xD;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;&#xD;
&lt;/fieldset&gt;&#xD;
&lt;p&gt;验证客户端输入的数据是否正确的方法，是基类提供的&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b;"&gt;&#xD;
&lt;pre&gt;protected bool FormHasError(DependencyObject form)&#xD;
        {&#xD;
            var items = form.GetVisuals();&#xD;
            foreach (var formItem in items)&#xD;
            {&#xD;
                if (Validation.GetHasError(formItem))&#xD;
                {&#xD;
                    ((Control)formItem).Focus();&#xD;
                    return true;&#xD;
                }&#xD;
            }&#xD;
            return false;&#xD;
        }&lt;/pre&gt;&#xD;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;&#xD;
&lt;/fieldset&gt;&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b;"&gt;&#xD;
&lt;pre&gt;public static IEnumerable&amp;lt;DependencyObject&amp;gt; GetVisuals(this DependencyObject root)&#xD;
        {&#xD;
            int count = VisualTreeHelper.GetChildrenCount(root);&#xD;
            for (int i = 0; i &amp;lt; count; i++)&#xD;
            {&#xD;
                var child = VisualTreeHelper.GetChild(root, i);&#xD;
                yield return child;&#xD;
                foreach (var descendants in child.GetVisuals())&#xD;
                {&#xD;
                    yield return descendants;&#xD;
                }&#xD;
            }&#xD;
        }&lt;/pre&gt;&#xD;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;&#xD;
&lt;/fieldset&gt;&#xD;
&lt;p&gt;如果某一个菜单项含有错误信息，那么将验证不通过。&lt;/p&gt;&#xD;
&lt;p&gt;Reload方法也是基类提供的&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b;"&gt;&#xD;
&lt;pre&gt;protected void Reload()&#xD;
        {&#xD;
            var t = this.GetType();&#xD;
            var ti = this.Parent as TabItem;&#xD;
            var menuObj = ti.DataContext as MenuM;&#xD;
            var tc = ti.Parent as TabControl;&#xD;
            tc.Items.Remove(ti);&#xD;
&#xD;
            var obj = Activator.CreateInstance(t);&#xD;
            ti = new Controls.PageContainer();&#xD;
            ti.DataContext = menuObj;&#xD;
            ti.Header = menuObj.MenuName;&#xD;
            ti.Content = obj;&#xD;
            tc.Items.Add(ti);&#xD;
            tc.SelectedItem = ti;&#xD;
        }&lt;/pre&gt;&#xD;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;&#xD;
&lt;/fieldset&gt;&#xD;
&lt;p&gt;此函数也结合前面的章节来看。&lt;/p&gt;&#xD;
&lt;p&gt;--------------------------------------&lt;/p&gt;&#xD;
&lt;p&gt;至此本系列全部写完了！&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://files.cnblogs.com/liulun/SL_FW.zip"&gt;源码下载&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;喜欢的请点推荐，支持我的文章。谢谢各位啦&lt;/p&gt;&lt;img src="http://www.cnblogs.com/liulun/aggbug/2337163.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/liulun/archive/2012/02/03/2337163.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/liulun/archive/2012/02/02/2336182.html</id><title type="text">SilverLight企业应用框架设计【五】客户端调用服务端（使用JSON传递数据，自己实现RESTful Web服务）</title><summary type="text">来个索引 SilverLight企业应用框架设计【四】实体层设计+为客户端动态生成服务代理(自己实现RiaService) SilverLight企业应用框架设计【三】服务端设计 SilverLight企业应用框架设计【二】框架画面 SilverLight企业应用框架设计【一】整体说明 在上一节中讲到的自动生成的服务代理类核心代码，如下 public event Servi...</summary><published>2012-02-02T12:34:00Z</published><updated>2012-02-02T12:34:00Z</updated><author><name>liulun</name><uri>http://www.cnblogs.com/liulun/</uri></author><link rel="alternate" href="http://www.cnblogs.com/liulun/archive/2012/02/02/2336182.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/liulun/archive/2012/02/02/2336182.html"/><content type="html">&lt;p&gt;来个索引&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.cnblogs.com/liulun/archive/2012/02/01/2335138.html"&gt;SilverLight企业应用框架设计【四】实体层设计+为客户端动态生成服务代理(自己实现RiaService)&lt;/a&gt;  &lt;p&gt;&lt;a href="http://www.cnblogs.com/liulun/archive/2012/01/05/2313674.html"&gt;SilverLight企业应用框架设计【三】服务端设计&lt;/a&gt;  &lt;p&gt;&lt;a href="http://www.cnblogs.com/liulun/archive/2012/01/04/2312482.html"&gt;SilverLight企业应用框架设计【二】框架画面&lt;/a&gt;  &lt;p&gt;&lt;a href="http://www.cnblogs.com/liulun/archive/2012/01/03/2311072.html"&gt;SilverLight企业应用框架设计【一】整体说明&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;在上一节中讲到的自动生成的服务代理类核心代码，如下&lt;/p&gt; &lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b"&gt;&lt;pre&gt;public event ServiceEventHandler Completed;&#xD;
        public void GetAllMenu()&#xD;
        {&#xD;
            var si = new ServiceInvoker();&#xD;
            si.Completed += new ServiceEventHandler(si_Completed);&#xD;
            si.PrepareInvoke("MenuService", "GetAllMenu", typeof(List&amp;lt;MenuM&amp;gt;));&#xD;
            si.InvokeService();&#xD;
        }&#xD;
        void si_Completed(object sender, ServiceEventArgs e)&#xD;
        {&#xD;
            Completed(sender, e);&#xD;
        }&lt;/pre&gt;&#xD;
&lt;div&gt;&lt;/div&gt;&lt;/fieldset&gt;&#xD;
&lt;p&gt;大家注意到我们是通过ServiceInvoker来调用服务的&lt;/p&gt;&#xD;
&lt;p&gt;实例化ServiceInvoker类之后就注册了ServiceEventHandler事件&lt;/p&gt;&#xD;
&lt;p&gt;此事件是服务调用完成后触发的事件（silverlight 原生的ria service也有一个completed事件）&lt;/p&gt;&#xD;
&lt;p&gt;该事件相关代码如下&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b"&gt;&lt;pre&gt;public class ServiceEventArgs : EventArgs&#xD;
    {&#xD;
        //服务方法的返回值&#xD;
        public object Result { get; set; }&#xD;
    }&#xD;
    public delegate void ServiceEventHandler(object sender, ServiceEventArgs e);&lt;/pre&gt;&#xD;
&lt;div&gt;&lt;/div&gt;&lt;/fieldset&gt;&#xD;
&lt;p&gt;在si.PrepareInvoke把需要调用的服务类名，方法名，返回值类型（如果有参数，这里还会自动加入参数）&lt;/p&gt;&#xD;
&lt;p&gt;PrepareInvoke方法如下&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b"&gt;&lt;pre&gt;public void PrepareInvoke(string ClassName,string MethodName,Type ResultType,params object[] objs)&#xD;
        {&#xD;
            className = ClassName;&#xD;
            methodName = MethodName;&#xD;
            resultType = ResultType;&#xD;
            MemoryStream ms = new MemoryStream();&#xD;
            var sb = new StringBuilder();            &#xD;
            for(int i=0;i&amp;lt;objs.Length;i++)&#xD;
            {&#xD;
                var jsonSerializer = new DataContractJsonSerializer(objs[i].GetType());&#xD;
                jsonSerializer.WriteObject(ms, objs[i]);&#xD;
                var objStr = Encoding.UTF8.GetString(ms.ToArray(), 0, (int)ms.Length);&#xD;
                ms.Position = 0;&#xD;
                sb.AppendFormat("p{0}=", i);&#xD;
                sb.AppendFormat("{0}", objStr);&#xD;
                sb.Append("&amp;amp;");&#xD;
            }&#xD;
            ms.Close();&#xD;
            paramStr = sb.ToString();&#xD;
        }&lt;/pre&gt;&#xD;
&lt;div&gt;&lt;/div&gt;&lt;/fieldset&gt;&#xD;
&lt;p&gt;在此方法中主要是记录下这些信息，&lt;/p&gt;&#xD;
&lt;p&gt;另外把服务需要传入的参数序列化成JSON字符串&lt;/p&gt;&#xD;
&lt;p&gt;紧接着就调用InvokeService方法&lt;/p&gt;&#xD;
&lt;p&gt;代码如下&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b"&gt;&lt;pre&gt;public void InvokeService()&#xD;
        {&#xD;
            Uri serviceUri = new Uri("http://localhost/RTMDemo.Host/RTMDemo.Host.WCF.MenuService");&#xD;
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(serviceUri);            &#xD;
            request.Method = "POST";&#xD;
            request.ContentType = "application/x-www-form-urlencoded";&#xD;
            var requestResult = request.BeginGetRequestStream(new AsyncCallback(RequestReady), request);&#xD;
            return;&#xD;
        }&lt;/pre&gt;&#xD;
&lt;div&gt;&lt;/div&gt;&lt;/fieldset&gt;&#xD;
&lt;p&gt;明眼人一看就明了了&lt;/p&gt;&#xD;
&lt;p&gt;其实就是使用HTTPWebRequest来调用服务（&lt;a href="http://www.cnblogs.com/liulun/archive/2012/01/05/2313674.html"&gt;服务端我们托管了HttpHandler的请求&lt;/a&gt;）&lt;/p&gt;&#xD;
&lt;p&gt;RequestReady事件如下：&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b"&gt;&lt;pre&gt;void RequestReady(IAsyncResult asyncResult)&#xD;
        {&#xD;
            HttpWebRequest request = asyncResult.AsyncState as HttpWebRequest;&#xD;
            Stream stream = request.EndGetRequestStream(asyncResult);&#xD;
            Deployment.Current.Dispatcher.BeginInvoke(delegate()&#xD;
            {&#xD;
                StreamWriter writer = new StreamWriter(stream);&#xD;
                writer.Write(paramStr);&#xD;
                writer.Write("MethodKey=RTMDemo.Host.WCF.{0}.{1}&amp;amp;", className,methodName);&#xD;
                writer.Flush();&#xD;
                writer.Close();&#xD;
                request.BeginGetResponse(new AsyncCallback(ResponseReady), request);&#xD;
            });&#xD;
        }&lt;/pre&gt;&#xD;
&lt;div&gt;&lt;/div&gt;&lt;/fieldset&gt;&#xD;
&lt;p&gt;在此事件中我们把服务类名方法名和参数写入了请求流&lt;/p&gt;&#xD;
&lt;p&gt;ResponseReady事件如下&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b"&gt;&lt;pre&gt;void ResponseReady(IAsyncResult asyncResult)&#xD;
        {&#xD;
            HttpWebRequest request = asyncResult.AsyncState as HttpWebRequest;&#xD;
            HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asyncResult);&#xD;
            Deployment.Current.Dispatcher.BeginInvoke(delegate()&#xD;
            {&#xD;
                Stream responseStream = response.GetResponseStream();&#xD;
                if (resultType == null)&#xD;
                {&#xD;
                    Completed(this, null);&#xD;
                    return;&#xD;
                }&#xD;
                try&#xD;
                {&#xD;
                    DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(resultType);&#xD;
                    result = jsonSerializer.ReadObject(responseStream);&#xD;
                }&#xD;
                catch&#xD;
                {&#xD;
                }&#xD;
                var se = new ServiceEventArgs();&#xD;
                se.Result = result;&#xD;
                Completed(this, se);&#xD;
            });&#xD;
        }&lt;/pre&gt;&#xD;
&lt;div&gt;&lt;/div&gt;&lt;/fieldset&gt;&#xD;
&lt;p&gt;这个事件把服务端返回的结果（JSON数据）反序列化成实体类型，并赋值给ServiceEventArgs&lt;/p&gt;&#xD;
&lt;p&gt;然后触发了Completed事件&lt;/p&gt;&#xD;
&lt;p&gt;也就是触发我们服务端代理类的si_Completed事件&lt;/p&gt;&#xD;
&lt;p&gt;至此，调用服务端的类就解释完了&lt;/p&gt;&#xD;
&lt;p&gt;下面我们看看是怎么调用服务端的&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b"&gt;&lt;pre&gt;private void InitMenu()&#xD;
        {&#xD;
            var ms = new MenuService();&#xD;
            ms.Completed += new ServiceEventHandler((o, re) =&amp;gt;&#xD;
            {                &#xD;
                var AllMenu = re.Result as List&amp;lt;MenuM&amp;gt;;&#xD;
                Common.ViewUtility.AllMenu = AllMenu;&#xD;
                InitTopMenu();&#xD;
            });&#xD;
            ms.GetAllMenu();&#xD;
        }&lt;/pre&gt;&#xD;
&lt;div&gt;&lt;/div&gt;&lt;/fieldset&gt;&#xD;
&lt;p&gt;看看是不是与ria service调用的方法有点像呢？&lt;/p&gt;&#xD;
&lt;p&gt;…………………………………………………………………………喜欢的话……………请推荐吧………………………………………………………&lt;/p&gt;&#xD;
&lt;p&gt;估计再写一篇就完结了&lt;/p&gt;&#xD;
&lt;p&gt;下一篇公布源码&lt;/p&gt;&lt;img src="http://www.cnblogs.com/liulun/aggbug/2336182.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/liulun/archive/2012/02/02/2336182.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/liulun/archive/2012/02/01/2335138.html</id><title type="text">SilverLight企业应用框架设计【四】实体层设计+为客户端动态生成服务代理(自己实现RiaService)</title><summary type="text">题外话： 对不住各位，本打算年前把这个系列写完，结果由于杂务缠身一直推到年后 我特别痛恨我自己！我觉得不但对不起各位！也对不起自己。 最近烦躁不安，不能专心向学。也不知道如何是好。 …… 好吧，言归正传 说个前提条件： 此项目虽然使用了silverlight 4.0 但是服务端只能在dotNet3.5下运行 这也是我们为什么自己实现riaService的原因 实体层设计 由于有这个限制条件，我...</summary><published>2012-02-01T14:00:00Z</published><updated>2012-02-01T14:00:00Z</updated><author><name>liulun</name><uri>http://www.cnblogs.com/liulun/</uri></author><link rel="alternate" href="http://www.cnblogs.com/liulun/archive/2012/02/01/2335138.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/liulun/archive/2012/02/01/2335138.html"/><content type="html">&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt; &lt;p&gt;题外话：&lt;/p&gt; &lt;p&gt;对不住各位，本打算年前把这个系列写完，结果由于杂务缠身一直推到年后&lt;/p&gt; &lt;p&gt;我特别痛恨我自己！我觉得不但对不起各位！也对不起自己。&lt;/p&gt; &lt;p&gt;最近烦躁不安，不能专心向学。也不知道如何是好。&lt;/p&gt; &lt;p&gt;……&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&lt;font color="#333333"&gt;好吧，言归正传&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font color="#333333"&gt;说个前提条件：&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font color="#333333"&gt;此项目虽然使用了silverlight 4.0 &lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font color="#333333"&gt;但是服务端只能在dotNet3.5下运行&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font color="#333333"&gt;这也是我们为什么自己实现riaService的原因&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;font color="#ff0000"&gt;实体层设计&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;font color="#333333"&gt;由于有这个限制条件，我们设计的实体层也有所区别&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font color="#333333"&gt;如下图为实体层的程序集（只有MenuM实体类，其他实体类未加入。）&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/liulun/201202/201202012200187558.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/liulun/201202/201202012200187906.png" width="212" height="156"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;下面来看一下实体层MenuM的代码&lt;/p&gt; &lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b"&gt;&lt;pre&gt;namespace RTMDemo.Model&#xD;
{&#xD;
    [DataContract]&#xD;
    public class MenuM : Entity&#xD;
    {&#xD;
        public string _MenuName;&#xD;
        public string _Url;&#xD;
        public string _MenuDes;&#xD;
        public int _OrderNum;&#xD;
        [DataMember]        &#xD;
        public Guid Id { get; set; }&#xD;
        [DataMember]&#xD;
        [Display(Name = "菜单名称")]&#xD;
        [Required(ErrorMessage="不能为空")]&#xD;
        public string MenuName&#xD;
        {&#xD;
            get&#xD;
            {&#xD;
                return _MenuName;&#xD;
            }&#xD;
            set&#xD;
            {&#xD;
                ValidateProperty("MenuName", value);&#xD;
                _MenuName = value;&#xD;
            }&#xD;
        }&#xD;
        [DataMember]&#xD;
        public Guid ParentId { get; set; }&#xD;
        [DataMember]&#xD;
        [Display(Name = "菜单路径")]&#xD;
        [Required(ErrorMessage = "不能为空")]&#xD;
        public string Url&#xD;
        {&#xD;
            get&#xD;
            {&#xD;
                return _Url;&#xD;
            }&#xD;
            set&#xD;
            {&#xD;
                ValidateProperty("Url", value);&#xD;
                _Url = value;&#xD;
            }&#xD;
        }&#xD;
        [DataMember]&#xD;
        [Display(Name = "菜单帮助")]&#xD;
        public string MenuDes&#xD;
        {&#xD;
            get&#xD;
            {&#xD;
                return _MenuDes;&#xD;
            }&#xD;
            set&#xD;
            {&#xD;
                ValidateProperty("Help", value);&#xD;
                _MenuDes = value;&#xD;
            }&#xD;
        }&#xD;
        [DataMember]&#xD;
        [Display(Name = "菜单排序")]&#xD;
        [RegularExpression("[1-9]+[0-9]", ErrorMessage = "只能输入数字")]&#xD;
        public int OrderNum&#xD;
        {&#xD;
            get&#xD;
            {&#xD;
                return _OrderNum;&#xD;
            }&#xD;
            set&#xD;
            {&#xD;
                ValidateProperty("MenuName", value);&#xD;
                _OrderNum = value;&#xD;
            }&#xD;
        }&#xD;
    }&#xD;
}&lt;/pre&gt;&#xD;
&lt;div&gt;&lt;/div&gt;&lt;/fieldset&gt; &#xD;
&lt;p&gt;这里有几点需要说明&lt;/p&gt;&#xD;
&lt;p&gt;1：&lt;/p&gt;&#xD;
&lt;p&gt;特性[DataContract]与[DataMember]标记&lt;/p&gt;&#xD;
&lt;p&gt;是为了客户端与服务端传输数据的时候序列化与反序列化引入的&lt;/p&gt;&#xD;
&lt;p&gt;2：&lt;/p&gt;&#xD;
&lt;p&gt;MenuM类继承自Entity类&lt;/p&gt;&#xD;
&lt;p&gt;然而在.net 3.5中是没有Entity类的&lt;/p&gt;&#xD;
&lt;p&gt;那么我们就创建了这个类（就是Attr文件夹下的 Entity.cs类）&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b"&gt;&lt;pre&gt;namespace System.ServiceModel.DomainServices.Client&#xD;
{&#xD;
    [DataContract]&#xD;
    public class Entity&#xD;
    {&#xD;
        public void ValidateProperty(string PropertyName, object value)&#xD;
        {&#xD;
        }&#xD;
    }&#xD;
}&lt;/pre&gt;&#xD;
&lt;div&gt;&lt;/div&gt;&lt;/fieldset&gt; &#xD;
&lt;p&gt;这个类虽然在这里看上去没什么用&lt;/p&gt;&#xD;
&lt;p&gt;但是在silverlight客户端用处就非常大（等会会说道为silverlight客户端自动生成实体类型，silverlight 4.0是有Entity类的）&lt;/p&gt;&#xD;
&lt;p&gt;3：&lt;/p&gt;&#xD;
&lt;p&gt;[Display(Name = "菜单名称")]&lt;/p&gt;&#xD;
&lt;p&gt;如上：Display特性在dotNet3.5中也是不存在的&lt;/p&gt;&#xD;
&lt;p&gt;同理，我们创建了DisplayAttribute特性，也是为了使用Silverlight4.0的客户端特性&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b"&gt;&lt;pre&gt;namespace System.ComponentModel.DataAnnotations&#xD;
{&#xD;
    public sealed class DisplayAttribute : Attribute&#xD;
    {&#xD;
        public string Name { get; set; }&#xD;
    }&#xD;
}&lt;/pre&gt;&#xD;
&lt;div&gt;&lt;/div&gt;&lt;/fieldset&gt; &#xD;
&lt;p&gt;&lt;strong&gt;&lt;font color="#ff0000"&gt;为客户端动态生成服务代理和实体类型&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;使用过Silverlight RIA Service的人一定都知道&lt;/p&gt;&#xD;
&lt;p&gt;每次编译的时候都会在Silverlight程序集中生成如下目录和文件&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/liulun/201202/2012020122001999.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/liulun/201202/201202012200193479.png" width="204" height="41"&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;此文件就包含了服务代理和实体类型&lt;/p&gt;&#xD;
&lt;p&gt;那么为了达到与RIA Service一样的效果&lt;/p&gt;&#xD;
&lt;p&gt;我们为服务端程序集增加了VS2010的后期生成事件命令行&lt;/p&gt;&#xD;
&lt;p&gt;如下图所示&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/liulun/201202/201202012200194592.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/liulun/201202/201202012200192989.png" width="476" height="340"&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;命令行代码为&lt;/p&gt;&#xD;
&lt;p&gt;$(SolutionDir)RTMDemo.Compile\bin\Debug\RTMDemo.Compile.exe&lt;/p&gt;&#xD;
&lt;p&gt;其中&lt;/p&gt;&#xD;
&lt;p&gt;$(SolutionDir)为宏，指解决方案的目录（定义为驱动器 + 路径）；包括尾部的反斜杠“\”。&lt;/p&gt;&#xD;
&lt;p&gt;更多生成事件命令行的宏请参见这里：&lt;a title="http://msdn.microsoft.com/zh-cn/library/42x5kfw4(v=vs.90).aspx" href="http://msdn.microsoft.com/zh-cn/library/42x5kfw4(v=vs.90).aspx"&gt;http://msdn.microsoft.com/zh-cn/library/42x5kfw4(v=vs.90).aspx&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;这个命令行的意思是&lt;/p&gt;&#xD;
&lt;p&gt;在编译完服务端类库后&lt;/p&gt;&#xD;
&lt;p&gt;执行RTMDemo.Compile\bin\Debug\RTMDemo.Compile.exe&lt;/p&gt;&#xD;
&lt;p&gt;也就是这个类库的生成文件&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/liulun/201202/201202012200196054.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/liulun/201202/201202012200201626.png" width="189" height="109"&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;那么我们来看一下这个程序集中的主要工作&lt;/p&gt;&#xD;
&lt;p&gt;1.保存目录路径以备读取和写入&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b"&gt;&lt;pre&gt;[DllImport("Kernel32.dll")]&#xD;
        public static extern string GetCommandLineA();&#xD;
        //实体的路径&#xD;
        static string mPath;&#xD;
        //服务的路径&#xD;
        static string sPath;&#xD;
        //客户端的路径&#xD;
        static string tarPath;&#xD;
        [STAThread]&#xD;
        static void Main()&#xD;
        {&#xD;
            var rtstr = @"RTMDemo.Compile\bin\Debug\RTMDemo.Compile.exe";&#xD;
            //获取命令行参数&#xD;
            var arg = GetCommandLineA().Replace("\"","");&#xD;
            mPath = arg.Replace(rtstr,"RTMDemo.Model");&#xD;
            sPath = arg.Replace(rtstr, @"RTMDemo.Host\bin\RTMDemo.Host.dll");&#xD;
            tarPath = arg.Replace(rtstr, @"RTMDemo.Frame\Generated_Code\RTMDemo.Host.g.cs");&#xD;
&#xD;
            AddModels();&#xD;
            AddService();&#xD;
        }&lt;/pre&gt;&#xD;
&lt;div&gt;&lt;/div&gt;&lt;/fieldset&gt; &#xD;
&lt;p&gt;2.添加实体类型&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b"&gt;&lt;pre&gt;static void AddModels()&#xD;
        {&#xD;
            var di = new DirectoryInfo(mPath);&#xD;
            var sb = new StringBuilder(Environment.NewLine);&#xD;
            foreach (var fi in di.GetFiles())&#xD;
            {&#xD;
                var pname = Path.GetFileNameWithoutExtension(fi.Name);&#xD;
                if (!pname.EndsWith("M"))&#xD;
                {&#xD;
                    continue;&#xD;
                }&#xD;
                var sr = new StreamReader(fi.FullName);&#xD;
                var content = sr.ReadToEnd();&#xD;
                var matche = Regex.Match(content, @"\[DataContract(.|\n)*}");&#xD;
                var str = matche.Value;&#xD;
                str = str.TrimEnd('}');&#xD;
                sb.Append(Environment.NewLine);&#xD;
                sb.AppendFormat("    {0}", str);&#xD;
                sr.Close();&#xD;
            }&#xD;
            sb.Append(Environment.NewLine);&#xD;
            WriteToTar("实体", sb.ToString());&#xD;
        }&lt;/pre&gt;&#xD;
&lt;div&gt;&lt;/div&gt;&lt;/fieldset&gt;&#xD;
&lt;p&gt;此端代码大意为：&lt;/p&gt;&#xD;
&lt;p&gt;遍历实体类库文件夹内的文件，&lt;/p&gt;&#xD;
&lt;p&gt;读取文件名以M结尾的文件（约定实体类名必须以M结尾）&lt;/p&gt;&#xD;
&lt;p&gt;然后按正则匹配[DataContract]以后的内容&lt;/p&gt;&#xD;
&lt;p&gt;把这些内容保存起来以备写入目标文件&lt;/p&gt;&#xD;
&lt;p&gt;3.添加服务代理&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b"&gt;&lt;pre&gt;static void AddService()&#xD;
        {&#xD;
            &#xD;
            var ass = Assembly.LoadFile(sPath);&#xD;
            var types = ass.GetTypes();&#xD;
            var sb = new StringBuilder(Environment.NewLine);&#xD;
            foreach (var ty in types)&#xD;
            {&#xD;
                if (!ty.Name.EndsWith("Service"))&#xD;
                {&#xD;
                    continue;&#xD;
                }&#xD;
                sb.AppendLine(string.Format("public class {0}", ty.Name));&#xD;
                sb.AppendLine("{");&#xD;
                sb.AppendLine("public event ServiceEventHandler Completed;");&#xD;
                var methods = ty.GetMethods();&#xD;
                foreach (var me in methods)&#xD;
                {&#xD;
                    if (me.DeclaringType != ty)&#xD;
                    {&#xD;
                        continue;&#xD;
                    }&#xD;
                    sb.AppendFormat("public void {0}(", me.Name);&#xD;
                    var Parameters = me.GetParameters();&#xD;
                    var ps = new StringBuilder();&#xD;
                    for (var i = 0; i &amp;lt; Parameters.Length; i++)&#xD;
                    {&#xD;
                        var tn = GetTypeName(Parameters[i].ParameterType);&#xD;
                        var dh = (i == Parameters.Length - 1?"":",");&#xD;
                        sb.AppendFormat("{0} {1}{2}", tn, Parameters[i].Name,dh);&#xD;
                        ps.AppendFormat(" ,{0}", Parameters[i].Name);&#xD;
                    }&#xD;
                    sb.AppendFormat("){0}", Environment.NewLine);&#xD;
                    sb.AppendLine("{");&#xD;
                    sb.AppendLine("var si = new ServiceInvoker();");&#xD;
                    sb.AppendLine("si.Completed += new ServiceEventHandler(si_Completed);");&#xD;
                    var rtp = GetTypeName(me.ReturnType);&#xD;
                    if (rtp == "Void")&#xD;
                    {&#xD;
                        sb.AppendLine(string.Format("si.PrepareInvoke(\"{0}\", \"{1}\", {2} {3});",&#xD;
                            ty.Name, me.Name, "null", ps.ToString()));&#xD;
                    }&#xD;
                    else&#xD;
                    {&#xD;
                        sb.AppendLine(string.Format("si.PrepareInvoke(\"{0}\", \"{1}\", typeof({2}) {3});", &#xD;
                                    ty.Name, me.Name, rtp, ps.ToString()));&#xD;
                    }&#xD;
                    sb.AppendLine("si.InvokeService();");&#xD;
                    sb.AppendLine("}");&#xD;
                }&#xD;
                sb.AppendLine("void si_Completed(object sender, ServiceEventArgs e)");&#xD;
                sb.AppendLine("{");&#xD;
                sb.AppendLine("Completed(sender, e);");&#xD;
                sb.AppendLine("}");&#xD;
                sb.AppendLine("}");&#xD;
            }&#xD;
            sb.Append(Environment.NewLine);&#xD;
            WriteToTar("服务", sb.ToString());&#xD;
        }&lt;/pre&gt;&#xD;
&lt;div&gt;&lt;/div&gt;&lt;/fieldset&gt;&#xD;
&lt;p&gt;获取服务端类信息与获取实体类信息不同&lt;/p&gt;&#xD;
&lt;p&gt;获取服务端类信息使用了反射&lt;/p&gt;&#xD;
&lt;p&gt;我们反射出类的名字，类中的方法名，参数名，参数类型，返回值类型等&lt;/p&gt;&#xD;
&lt;p&gt;来生成形如下面这样的服务端代理&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b"&gt;&lt;pre&gt;public class MenuService&#xD;
    {&#xD;
        public event ServiceEventHandler Completed;&#xD;
        public void GetAllMenu()&#xD;
        {&#xD;
            var si = new ServiceInvoker();&#xD;
            si.Completed += new ServiceEventHandler(si_Completed);&#xD;
            si.PrepareInvoke("MenuService", "GetAllMenu", typeof(List&amp;lt;MenuM&amp;gt;));&#xD;
            si.InvokeService();&#xD;
        }&#xD;
        public void DelMenu(Guid Id)&#xD;
        {&#xD;
            var si = new ServiceInvoker();&#xD;
            si.Completed += new ServiceEventHandler(si_Completed);&#xD;
            si.PrepareInvoke("MenuService", "DelMenu", null, Id);&#xD;
            si.InvokeService();&#xD;
        }&#xD;
        public void AddMenu(MenuM m)&#xD;
        {&#xD;
            var si = new ServiceInvoker();&#xD;
            si.Completed += new ServiceEventHandler(si_Completed);&#xD;
            si.PrepareInvoke("MenuService", "AddMenu", null, m);&#xD;
            si.InvokeService();&#xD;
        }&#xD;
        public void UpdateMenu(MenuM m)&#xD;
        {&#xD;
            var si = new ServiceInvoker();&#xD;
            si.Completed += new ServiceEventHandler(si_Completed);&#xD;
            si.PrepareInvoke("MenuService", "UpdateMenu", null, m);&#xD;
            si.InvokeService();&#xD;
        }&#xD;
        void si_Completed(object sender, ServiceEventArgs e)&#xD;
        {&#xD;
            Completed(sender, e);&#xD;
        }&#xD;
    }&lt;/pre&gt;&#xD;
&lt;div&gt;&lt;/div&gt;&lt;/fieldset&gt;&#xD;
&lt;p&gt;至于ServiceInvoker是什么，我们将在下一节内容中介绍&lt;/p&gt;&#xD;
&lt;p&gt;注意：这样生成服务端代理暂不支持生成服务端方法的重载代理&lt;/p&gt;&#xD;
&lt;p&gt;在获取参数或返回值类型的时候，&lt;/p&gt;&#xD;
&lt;p&gt;会遇到获取泛型类型的情况（如：List~&amp;lt;….&amp;gt;，就不能把这些拼到字符串内去）&lt;/p&gt;&#xD;
&lt;p&gt;我们使用诸如下面的函数来做简单判别&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b"&gt;&lt;pre&gt;public static string GetTypeName(Type t)&#xD;
        {&#xD;
            if (t.Name.StartsWith("List"))&#xD;
            {&#xD;
                var gtype = t.GetGenericArguments().FirstOrDefault();&#xD;
                var result = string.Format("List&amp;lt;{0}&amp;gt;", gtype.Name);&#xD;
                return result;&#xD;
            }&#xD;
            return t.Name;&#xD;
        }&lt;/pre&gt;&#xD;
&lt;div&gt;&lt;/div&gt;&lt;/fieldset&gt;&#xD;
&lt;p&gt;4.写入代理文件&lt;/p&gt;&#xD;
&lt;p&gt;原始的代理文件模版如下&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b"&gt;&lt;pre&gt;//------------------------------------------------------------------------------&#xD;
// &amp;lt;auto-generated&amp;gt;&#xD;
//     此代码由工具生成。&#xD;
//     对此文件的更改可能会导致不正确的行为，&#xD;
//     并且如果重新生成代码，这些更改将会丢失。&#xD;
// &amp;lt;/auto-generated&amp;gt;&#xD;
//------------------------------------------------------------------------------&#xD;
&#xD;
namespace RTMDemo.Frame.Client&#xD;
{&#xD;
    using System;&#xD;
    using System.Collections.Generic;&#xD;
    using System.Runtime.Serialization;&#xD;
    using RTMDemo.Frame.Common;&#xD;
    using System.ComponentModel.DataAnnotations;&#xD;
    using System.ComponentModel;&#xD;
    using System.ServiceModel.DomainServices.Client;&#xD;
    #region 实体&#xD;
&#xD;
    #endregion&#xD;
&#xD;
    #region 服务&#xD;
&#xD;
&#xD;
    #endregion&#xD;
}&lt;/pre&gt;&#xD;
&lt;div&gt;&lt;/div&gt;&lt;/fieldset&gt;&#xD;
&lt;p&gt;写入代理文件主要是匹配两个region&lt;/p&gt;&#xD;
&lt;p&gt;然后插入之前生成的字符串&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b"&gt;&lt;pre&gt;static void WriteToTar(string reg, string content)&#xD;
        {&#xD;
            reg = string.Format(@"(?&amp;lt;=#region {0})(.|\n)*?(?=#endregion)", reg);&#xD;
            var tsr = new StreamReader(tarPath);&#xD;
            var tcontent = tsr.ReadToEnd();&#xD;
            tsr.Close();&#xD;
            tcontent = Regex.Replace(tcontent, reg, content);&#xD;
            var tarStream = new StreamWriter(tarPath);&#xD;
            tarStream.Write(tcontent);&#xD;
            tarStream.Close();&#xD;
        }&lt;/pre&gt;&#xD;
&lt;div&gt;&lt;/div&gt;&lt;/fieldset&gt;&#xD;
&lt;p&gt;调用此函数的代码如下&lt;/p&gt;&#xD;
&lt;p&gt;WriteToTar("服务", sb.ToString());&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;至此就把服务代理和实体类型都拷贝到客户端去了&lt;/p&gt;&#xD;
&lt;p&gt;在下一节我们介绍怎么使用这些内容&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;………………………………………….写文章不容易…………………请务必点个推荐吧………………………………………………&lt;/p&gt;&lt;img src="http://www.cnblogs.com/liulun/aggbug/2335138.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/liulun/archive/2012/02/01/2335138.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/liulun/archive/2012/01/09/2317036.html</id><title type="text">【翻译】.NET Framework 4.5新特性</title><summary type="text">开发者预览版.net 4.5.NET for Metro style appsMetro风格的应用程序是利用Windows操作系统的强大功能设计的特殊表单元素。一个称之为.NET APIs for Metro style apps的.Net的一个子集用来支持Metro风格的应用程序，可以使用C#或Visual Basic来编写Metro风格的应用程序。详见：http://go.microsoft.com/fwlink/?LinkId=228491核心新功能和改进以下这些功能和改进被添加到公共语言运行时（CLR）和.NET的类内：-设置正则表达式执行匹配的超时时间-为应用程序域设置区域性信息-控</summary><published>2012-01-09T05:54:00Z</published><updated>2012-01-09T05:54:00Z</updated><author><name>liulun</name><uri>http://www.cnblogs.com/liulun/</uri></author><link rel="alternate" href="http://www.cnblogs.com/liulun/archive/2012/01/09/2317036.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/liulun/archive/2012/01/09/2317036.html"/><content type="html">&lt;p&gt;&lt;span style="color: #000000;"&gt;开发者预览版.net 4.5&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="color: #ff0000;"&gt;.NET for Metro style apps&lt;/span&gt;&lt;br /&gt;Metro风格的应用程序是利用Windows操作系统的强大功能设计的特殊表单元素。&lt;br /&gt;一个称之为.NET APIs for Metro style apps的.Net的一个子集用来支持Metro风格的应用程序，&lt;br /&gt;可以使用C#或Visual Basic来编写Metro风格的应用程序。&lt;br /&gt;详见：&lt;br /&gt;&lt;a href="http://go.microsoft.com/fwlink/?LinkId=228491"&gt;http://go.microsoft.com/fwlink/?LinkId=228491&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="color: #ff0000;"&gt;核心新功能和改进&lt;/span&gt;&lt;br /&gt;以下这些功能和改进被添加到公共语言运行时（CLR）和.NET的类内：&lt;br /&gt;-设置正则表达式执行匹配的超时时间&lt;br /&gt;-为应用程序域设置区域性信息&lt;br /&gt;-控制台应用支持Unicode（UTF-16）编码&lt;br /&gt;-支持按区域信息进行字符串比较和排序&lt;br /&gt;-提高了检索资源的性能&lt;br /&gt;-Zip压缩的改进，以减少一个压缩文件的大小&lt;br /&gt;-可以使用CustomReflectionContext类来自定义一个反射的上下文，以重写默认的反射行为&lt;br /&gt;（关于CustomReflectionContext类的信息，详见：&lt;a href="http://msdn.microsoft.com/zh"&gt;http://msdn.microsoft.com/zh-cn/library/system.reflection.context.customreflectioncontext(v=VS.110).aspx&lt;/a&gt;）&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="color: #ff0000;"&gt;Managed Extensibility Framework (MEF)&lt;/span&gt;&lt;br /&gt;-支持泛型类型&lt;br /&gt;-&amp;ldquo;约定优先&amp;rdquo;的编程模型。（你可以不必使用类特性来创建部件，现在可以按命名约定来创建你的部件）&lt;br /&gt;-多作用域&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="color: #ff0000;"&gt;异步文件操作&lt;/span&gt;&lt;br /&gt;在.NET框架4.5开发者预览版中，&lt;br /&gt;基于任务模型的异步操作特性被添加到C#和Visual Basic语言。&lt;br /&gt;使用asynchronous methods in the I/O classes可以使用这些新特性&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="color: #ff0000;"&gt;Web&lt;/span&gt; &lt;br /&gt;ASP.NET4.5开发预览版包括以下新的特点：&lt;br /&gt;-&lt;br /&gt;支持新的HTML5表单类型。&lt;br /&gt;-&lt;br /&gt;支持在Web Forms中进行模型绑定。&lt;br /&gt;可以直接把数据访问方法绑定到控件上&lt;br /&gt;可以自动把用户输入的数据进行格式转化&lt;br /&gt;-&lt;br /&gt;Support for unobtrusive JavaScript in client-side validation scripts&lt;br /&gt;（这一句不知道怎么翻~我也不明白这一句是什么意思.）&lt;br /&gt;-&lt;br /&gt;通过捆绑和压缩客户端脚本以提高性能&lt;br /&gt;-&lt;br /&gt;使用AntiXSS库对常规的表单进行编码，以防止跨站脚本攻击&lt;br /&gt;AntiXSS以前是一个外部类库，还包括SQL注入防御；详见：&lt;a href="http://wpl.codeplex.com/"&gt;http://wpl.codeplex.com/&lt;/a&gt;&lt;br /&gt;-&lt;br /&gt;支持的WebSockets协议&lt;br /&gt;（这应该是HTML5的内容，详见：&lt;a href="http://en.wikipedia.org/wiki/Web_Sockets"&gt;http://en.wikipedia.org/wiki/Web_Sockets&lt;/a&gt;）&lt;br /&gt;-&lt;br /&gt;支持异步读写HTTP的请求和响应&lt;br /&gt;-&lt;br /&gt;支持异步modules和handlers&lt;br /&gt;-&lt;br /&gt;使用ScriptManager支持内容分发网络（CDN）&lt;br /&gt;更多功能：&lt;br /&gt;&lt;a href="http://msdn.microsoft.com/zh-cn/library/hh420390(v=VS.110).aspx"&gt;http://msdn.microsoft.com/zh-cn/library/hh420390(v=VS.110).aspx&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="color: #ff0000;"&gt;Networking&amp;nbsp; 网络&lt;/span&gt;&lt;br /&gt;NET Framework4.5开发人员预览版提供了HTTP应用新的编程接口。&lt;br /&gt;更多详细信息，&lt;br /&gt;请见新版 System.Net.Http &lt;br /&gt;（&lt;a href="http://msdn.microsoft.com/zh-cn/library/system.net.http(v=VS.110).aspx"&gt;http://msdn.microsoft.com/zh-cn/library/system.net.http(v=VS.110).aspx&lt;/a&gt;）&lt;br /&gt;和 System.Net.Http.Headers&lt;br /&gt;（&lt;a href="http://msdn.microsoft.com/zh-cn/library/system.net.http.headers(v=VS.110).aspx"&gt;http://msdn.microsoft.com/zh-cn/library/system.net.http.headers(v=VS.110).aspx&lt;/a&gt;）&lt;br /&gt;命名空间。&lt;br /&gt;此外，下面的网络方面的改进包括System.Net，System.Net.Mail，以及相关的命名空间。&lt;br /&gt;-改进的国际化和IPv6支持。&lt;br /&gt;-RFC兼容的URI支持。&lt;br /&gt;-支持国际域名（IDN）分析。&lt;br /&gt;-电子邮件地址国际化（EAI）的支持。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="color: #ff0000;"&gt;Windows Presentation Foundation (WPF)&lt;/span&gt; &lt;br /&gt;在.NET框架4.5开发人员预览版中，Windows Presentation Foundation（WPF）包含以下几个方面的变化和改进：&lt;br /&gt;-新的&lt;a href="http://msdn.microsoft.com/zh-cn/library/system.windows.controls.ribbon.ribbon(v=VS.110).aspx"&gt;ribbon&lt;/a&gt;控件&lt;br /&gt;-新&lt;a href="http://msdn.microsoft.com/zh-cn/library/system.componentmodel.inotifydataerrorinfo(v=VS.110).aspx"&gt;INotifyDataErrorInfo&lt;/a&gt;接口，支持同步和异步数据验证&lt;br /&gt;-&lt;a href="http://msdn.microsoft.com/zh-cn/library/system.windows.controls.virtualizingpanel(v=VS.110).aspx"&gt;VirtualizingPanel&lt;/a&gt;和&lt;a href="http://msdn.microsoft.com/zh-cn/library/system.windows.threading.dispatcher(v=VS.110).aspx"&gt;Dispatcher&lt;/a&gt;类的新功能。&lt;br /&gt;-显示大集合数据和非UI线程访问集合时的性能改进&lt;br /&gt;-绑定到静态属性与绑定到自定义类型都实现了&lt;a href="http://msdn.microsoft.com/zh-cn/library/system.reflection.icustomtypeprovider(v=VS.110).aspx"&gt;ICustomTypeProvider&lt;/a&gt;接口，从绑定表达式提取数据绑定信息&lt;br /&gt;-对变化的值进行复位 (live shaping).&lt;br /&gt;-更好的集成WPF和Win32的用户界面组件。&lt;br /&gt;-可以检查容器的数据上下文是否断开链接。&lt;br /&gt;-可以设置属性、数据源改变的超时时间&lt;br /&gt;-实施弱事件模式的改进支持。此外，事件现在可以接受的扩展标记。&lt;br /&gt;欲了解更多信息：&lt;a href="http://msdn.microsoft.com/zh-cn/library/bb613588(v=VS.110).aspx"&gt;http://msdn.microsoft.com/zh-cn/library/bb613588(v=VS.110).aspx&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="color: #ff0000;"&gt;Windows Communication Foundation (WCF)&lt;/span&gt; &lt;br /&gt;-简化生成的配置文件&lt;br /&gt;-契约优先原则开发支持。&lt;br /&gt;-更容易的配置ASP.NET兼容性模式。&lt;br /&gt;-修改了默认传输属性，以减少开发人员通过编码设置它的次数。&lt;br /&gt;-更新的&lt;a href="http://msdn.microsoft.com/zh-cn/library/system.xml.xmldictionaryreaderquotas(v=VS.110).aspx"&gt;XmlDictionaryReaderQuotas&lt;/a&gt;类，以减少手动配置XML字典的读者配额的次数。&lt;br /&gt;-VisualStudio可以在编译时验证WCF配置文件是否正确，这样就避免了运行之后才能发现配置文件错误的问题。&lt;br /&gt;-新的异步流支持。&lt;br /&gt;-新的HTTPS协议映射，使IIS上的基于HTTPS协议的WCF服务更容易暴露终结点&lt;br /&gt;-通过在WCF服务URL中增加&amp;ldquo;?singleWSDL&amp;rdquo;可以生成WSDL元数据&lt;br /&gt;-WebSockets的支持，使得在80和443端口的双向通信方式与TCP传输类似。&lt;br /&gt;-支持在代码中配置服务（应该是运行期改变服务配置）&lt;br /&gt;-XML编辑器提示。&lt;br /&gt;-&lt;a href="http://msdn.microsoft.com/zh-cn/library/system.servicemodel.channelfactory(v=VS.110).aspx"&gt;ChannelFactory&lt;/a&gt;的缓存支持。&lt;br /&gt;-二进制编码压缩的支持&lt;br /&gt;更多：&lt;br /&gt;&lt;a href="http://go.microsoft.com/fwlink/?LinkId=228173"&gt;http://go.microsoft.com/fwlink/?LinkId=228173&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;原文地址&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://msdn.microsoft.com/library/ms171868%28VS.110%29.aspx#tailored"&gt;http://msdn.microsoft.com/library/ms171868%28VS.110%29.aspx#tailored&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;由于我对WF部分不熟&lt;/p&gt;&#xD;
&lt;p&gt;就没有翻译这一部分&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;-------------------------------------------------------------支持的请点推荐啊！！！---------------------------------------------------&lt;/p&gt;&lt;img src="http://www.cnblogs.com/liulun/aggbug/2317036.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/liulun/archive/2012/01/09/2317036.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/liulun/archive/2012/01/05/2313674.html</id><title type="text">SilverLight企业应用框架设计【三】服务端设计</title><summary type="text">一：缓存服务类型与方法 客户端请求的时候 为了方便的知道请求的类型与类型所包含的方法 我们把服务类型和方法缓存到静态字典中了 代码如下 public class WCFRouteTable { static Dictionary&amp;lt;string, Type&amp;gt; routeService; static Dictionary&amp;lt;string, MethodInfo...</summary><published>2012-01-05T13:45:00Z</published><updated>2012-01-05T13:45:00Z</updated><author><name>liulun</name><uri>http://www.cnblogs.com/liulun/</uri></author><link rel="alternate" href="http://www.cnblogs.com/liulun/archive/2012/01/05/2313674.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/liulun/archive/2012/01/05/2313674.html"/><content type="html">&lt;p&gt;&lt;font color="#ff0000"&gt;&lt;strong&gt;一：缓存服务类型与方法&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font color="#000000"&gt;客户端请求的时候&lt;/font&gt;&lt;/p&gt; &lt;p&gt;为了方便的知道请求的类型与类型所包含的方法&lt;/p&gt; &lt;p&gt;我们把服务类型和方法缓存到静态字典中了&lt;/p&gt; &lt;p&gt;代码如下&lt;/p&gt; &lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b"&gt;&lt;pre&gt;public class WCFRouteTable&#xD;
    {&#xD;
        static Dictionary&amp;lt;string, Type&amp;gt; routeService;&#xD;
        static Dictionary&amp;lt;string, MethodInfo&amp;gt; routeMethods;&#xD;
        static WCFRouteTable()&#xD;
        {&#xD;
            routeService = new Dictionary&amp;lt;string, Type&amp;gt;();&#xD;
            routeMethods = new Dictionary&amp;lt;string, MethodInfo&amp;gt;();&#xD;
            var ass = (typeof(WCFRouteTable)).Assembly;&#xD;
            var ts = ass.GetTypes();&#xD;
            foreach (var t in ts)&#xD;
            {&#xD;
                if (t.FullName.StartsWith("RTMDemo.Host.WCF"))&#xD;
                {&#xD;
                    routeService.Add(t.FullName, t);&#xD;
                    foreach (var m in t.GetMethods())&#xD;
                    {&#xD;
                        var mName = string.Format("{0}.{1}", t.FullName, m.Name);&#xD;
                        routeMethods.Add(mName, m);&#xD;
                    }&#xD;
                }&#xD;
            }&#xD;
        }&#xD;
        public static Type GetWCFType(string key)&#xD;
        {&#xD;
            Type result = null;&#xD;
            if (routeService.ContainsKey(key))&#xD;
            {&#xD;
                result = routeService[key];&#xD;
            }&#xD;
            return result;&#xD;
        }&#xD;
        public static MethodInfo GetMethodInfo(string key)&#xD;
        {&#xD;
            MethodInfo result = null;&#xD;
            if (routeMethods.ContainsKey(key))&#xD;
            {&#xD;
                result = routeMethods[key];&#xD;
            }&#xD;
            return result;&#xD;
        }&#xD;
&#xD;
    }&lt;/pre&gt;&#xD;
&lt;div&gt;&lt;/div&gt;&lt;/fieldset&gt;&#xD;
&lt;p&gt;&lt;font color="#ff0000"&gt;&lt;strong&gt;二：托管HTTP请求&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;在webconfig中增加module以托管请求&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b"&gt;&lt;pre&gt;&amp;lt;modules&amp;gt;&#xD;
            &amp;lt;add name="WcfHttpModule" type="RTMDemo.Host.WCFHttpModule, RTMDemo.Host"/&amp;gt;&#xD;
    &amp;lt;/modules&amp;gt;&lt;/pre&gt;&#xD;
&lt;div&gt;&lt;/div&gt;&lt;/fieldset&gt;&#xD;
&lt;p&gt;托管请求对应的类的代码如下&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b"&gt;&lt;pre&gt;public class WCFHttpModule:IHttpModule&#xD;
    {&#xD;
        public void Dispose() { }&#xD;
        /// &amp;lt;summary&amp;gt;&#xD;
        /// 托管请求&#xD;
        /// &amp;lt;/summary&amp;gt;&#xD;
        /// &amp;lt;param name="context"&amp;gt;&amp;lt;/param&amp;gt;&#xD;
        public void Init(HttpApplication context)&#xD;
        {&#xD;
            context.BeginRequest += (sender, args) =&amp;gt;&#xD;
            {&#xD;
                string relativeAddress = HttpContext.Current.Request.AppRelativeCurrentExecutionFilePath.Remove(0, 2);&#xD;
                Type serviceType = WCFRouteTable.GetWCFType(relativeAddress);&#xD;
                if (null == serviceType)&#xD;
                {&#xD;
                    return;&#xD;
                }&#xD;
                IHttpHandler handler = new WCFHandler(serviceType);&#xD;
                context.Context.RemapHandler(handler);&#xD;
            };&#xD;
        }&#xD;
    }&lt;/pre&gt;&#xD;
&lt;div&gt;&lt;/div&gt;&lt;/fieldset&gt;&#xD;
&lt;p&gt;通过这行代码&lt;/p&gt;&#xD;
&lt;p&gt;Type serviceType = WCFRouteTable.GetWCFType(relativeAddress);&lt;/p&gt;&#xD;
&lt;p&gt;用户只要请求如下路径&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://localhost/RTMDemo.Host/RTMDemo.Host.WCF.MenuService"&gt;http://localhost/RTMDemo.Host/RTMDemo.Host.WCF.MenuService&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;就会得到MenuService的类型&lt;/p&gt;&#xD;
&lt;p&gt;然后把服务类型传给指定的处理程序&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font color="#ff0000"&gt;&lt;strong&gt;三：处理请求&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;在WCFHandler类中最重要的莫过于&lt;/p&gt;&#xD;
&lt;p&gt;处理请求的方法&lt;/p&gt;&#xD;
&lt;p&gt;代码如下&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b"&gt;&lt;pre&gt;/// &amp;lt;summary&amp;gt;&#xD;
        /// 处理请求&#xD;
        /// &amp;lt;/summary&amp;gt;&#xD;
        /// &amp;lt;param name="context"&amp;gt;&amp;lt;/param&amp;gt;&#xD;
        public void ProcessRequest(HttpContext context)&#xD;
        {&#xD;
            try&#xD;
            {&#xD;
                List&amp;lt;object&amp;gt; paramList = new List&amp;lt;object&amp;gt;();&#xD;
                JavaScriptSerializer jss = new JavaScriptSerializer();&#xD;
                var MethodKey = context.Request["MethodKey"];&#xD;
                var minfo = WCFRouteTable.GetMethodInfo(MethodKey);&#xD;
                var si = new MethodInvoker(minfo);&#xD;
                ParameterInfo[] ps = minfo.GetParameters();&#xD;
                var pstrs = context.Request.Form.AllKeys.OrderBy(m=&amp;gt;m).ToArray();&#xD;
                var pIndex = 0;&#xD;
                for(var i=0;i&amp;lt;pstrs.Length;i++)&#xD;
                {&#xD;
                    if (string.IsNullOrEmpty(pstrs[i]))&#xD;
                    {&#xD;
                        continue;&#xD;
                    }&#xD;
                    if (pstrs[i].StartsWith("p"))&#xD;
                    {&#xD;
                        var pStr = context.Request[pstrs[i]];&#xD;
                        var obj = jss.Deserialize&amp;lt;object&amp;gt;(pStr);&#xD;
                        var bts = Encoding.UTF8.GetBytes(pStr);&#xD;
                        MemoryStream mss = new MemoryStream(Encoding.UTF8.GetBytes(pStr));&#xD;
                        DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(ps[pIndex].ParameterType);                &#xD;
                        var p = jsonSerializer.ReadObject(mss);&#xD;
                        paramList.Add(p);&#xD;
                        pIndex += 1;&#xD;
                    }&#xD;
                }&#xD;
&#xD;
                //todo:此处性能不佳&#xD;
                var instance = Activator.CreateInstance(ServiceType);&#xD;
                var result = si.Execute(instance,paramList.ToArray());&#xD;
                var ss = jss.Serialize(result);&#xD;
&#xD;
                context.Response.ClearContent();&#xD;
                context.Response.ContentEncoding = Encoding.UTF8;&#xD;
                context.Response.ContentType = "application/json; charset=utf-8";&#xD;
                context.Response.Write(ss);&#xD;
                context.Response.Flush();&#xD;
            }&#xD;
            catch&#xD;
            {&#xD;
                context.Response.Write("我们不提供此服务的元数据~&amp;lt;br /&amp;gt;");&#xD;
                context.Response.Write("@@@@@@~&amp;lt;br /&amp;gt;@@@@@@@~");&#xD;
                return;&#xD;
            }&#xD;
        }&#xD;
    }&lt;/pre&gt;&#xD;
&lt;div&gt;&lt;/div&gt;&lt;/fieldset&gt;&#xD;
&lt;p&gt;注意：首先说这段代码还有很大的优化空间；也未经过严格的测试；但思路基本就是这样的&lt;/p&gt;&#xD;
&lt;p&gt;处理请求主要做了如下几步工作：&lt;/p&gt;&#xD;
&lt;p&gt;1.&lt;/p&gt;&#xD;
&lt;p&gt;先根据请求POST上来的信息得到准备执行的方法&lt;/p&gt;&#xD;
&lt;p&gt;var MethodKey = context.Request["MethodKey"];&lt;br&gt;var minfo = WCFRouteTable.GetMethodInfo(MethodKey);&lt;/p&gt;&#xD;
&lt;p&gt;&lt;em&gt;MethodInvoker稍后再讲&lt;/em&gt;&lt;/p&gt;&#xD;
&lt;p&gt;2.&lt;/p&gt;&#xD;
&lt;p&gt;按顺序取出了方法的参数，并用DataContractJsonSerializer反序列化成对象&lt;/p&gt;&#xD;
&lt;p&gt;方法参数都是用JSON字符串传递的&lt;/p&gt;&#xD;
&lt;p&gt;3.&lt;/p&gt;&#xD;
&lt;p&gt;通过反射创建了服务的实例&lt;/p&gt;&#xD;
&lt;p&gt;然后调用该实例的方法&lt;/p&gt;&#xD;
&lt;p&gt;得到方法的返回值，并序列化成JSON字符串&lt;/p&gt;&#xD;
&lt;p&gt;4.&lt;/p&gt;&#xD;
&lt;p&gt;把返回值以JSON的形式输出给客户端&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;font color="#ff0000"&gt;四：其他&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font color="#000000"&gt;1.&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;MethodInvoker是用的&lt;a href="http://blog.zhaojie.me/"&gt;老赵&lt;/a&gt;的类；具体是哪篇文章，我已经找不到了。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b"&gt;&lt;pre&gt;public class MethodInvoker&#xD;
    {&#xD;
        private Func&amp;lt;object, object[], object&amp;gt; m_execute;&#xD;
&#xD;
        public MethodInvoker(MethodInfo methodInfo)&#xD;
        {&#xD;
            this.m_execute = this.GetExecuteDelegate(methodInfo);&#xD;
        }&#xD;
&#xD;
        public object Execute(object instance, params object[] parameters)&#xD;
        {&#xD;
            return this.m_execute(instance, parameters);            &#xD;
        }&#xD;
&#xD;
        private Func&amp;lt;object, object[], object&amp;gt; GetExecuteDelegate(MethodInfo methodInfo)&#xD;
        {&#xD;
            ParameterExpression instanceParameter = Expression.Parameter(typeof(object), "instance");&#xD;
            ParameterExpression parametersParameter = Expression.Parameter(typeof(object[]), "parameters");&#xD;
&#xD;
            List&amp;lt;Expression&amp;gt; parameterExpressions = new List&amp;lt;Expression&amp;gt;();&#xD;
            ParameterInfo[] paramInfos = methodInfo.GetParameters();&#xD;
            for (int i = 0; i &amp;lt; paramInfos.Length; i++)&#xD;
            {&#xD;
                var ce = Expression.Constant(i);&#xD;
                BinaryExpression valueObj = Expression.ArrayIndex(parametersParameter,ce);&#xD;
                UnaryExpression valueCast = Expression.Convert(valueObj, paramInfos[i].ParameterType);&#xD;
                parameterExpressions.Add(valueCast);&#xD;
            }&#xD;
            var instanceE = Expression.Convert(instanceParameter, methodInfo.ReflectedType);&#xD;
            Expression instanceCast = methodInfo.IsStatic ? null : instanceE;&#xD;
            MethodCallExpression methodCall = Expression.Call(instanceCast, methodInfo, parameterExpressions);&#xD;
            if (methodCall.Type == typeof(void))&#xD;
            {&#xD;
                Expression&amp;lt;Action&amp;lt;object, object[]&amp;gt;&amp;gt; lambda = Expression.Lambda&amp;lt;Action&amp;lt;object, object[]&amp;gt;&amp;gt;(methodCall, instanceParameter, parametersParameter);&#xD;
                Action&amp;lt;object, object[]&amp;gt; execute = lambda.Compile();&#xD;
                return (instance, parameters) =&amp;gt;&#xD;
                {&#xD;
                    execute(instance, parameters);&#xD;
                    return null;&#xD;
                };&#xD;
            }&#xD;
            else&#xD;
            {&#xD;
                UnaryExpression castMethodCall = Expression.Convert(methodCall, typeof(object));&#xD;
                Expression&amp;lt;Func&amp;lt;object, object[], object&amp;gt;&amp;gt; lambda =Expression.Lambda&amp;lt;Func&amp;lt;object, object[], object&amp;gt;&amp;gt;(castMethodCall, instanceParameter, parametersParameter);&#xD;
                return lambda.Compile();&#xD;
            }&#xD;
        }&#xD;
    }&lt;/pre&gt;&#xD;
&lt;div&gt;&lt;/div&gt;&lt;/fieldset&gt;&lt;/p&gt;&#xD;
&lt;p&gt;2.&lt;/p&gt;&#xD;
&lt;p&gt;服务类和数据访问的类没有什么特殊的&lt;/p&gt;&#xD;
&lt;p&gt;我这里只公布一个服务的类&lt;/p&gt;&#xD;
&lt;p&gt;&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b"&gt;&lt;pre&gt;public class MenuService&#xD;
    {&#xD;
        public List&amp;lt;MenuM&amp;gt; GetAllMenu()&#xD;
        {            &#xD;
            using (var DA = new MenuDA())&#xD;
            {&#xD;
                var result = DA.GetAllMenu();&#xD;
                return result;&#xD;
            }&#xD;
        }&#xD;
        public void DelMenu(Guid Id)&#xD;
        {&#xD;
            using (var DA = new MenuDA())&#xD;
            {&#xD;
                DA.DelMenu(Id);&#xD;
            }&#xD;
        }&#xD;
        public void AddMenu(MenuM m)&#xD;
        {&#xD;
            using (var DA = new MenuDA())&#xD;
            {&#xD;
                DA.AddMenu(m);&#xD;
            }&#xD;
        }&#xD;
        public void UpdateMenu(MenuM m)&#xD;
        {&#xD;
            using (var DA = new MenuDA())&#xD;
            {&#xD;
                DA.UpdateMenu(m);&#xD;
            }&#xD;
        }&#xD;
    }&lt;/pre&gt;&#xD;
&lt;div&gt;&lt;/div&gt;&lt;/fieldset&gt;&lt;/p&gt;&#xD;
&lt;p&gt;MenuDa就是数据访问类了&lt;/p&gt;&#xD;
&lt;p&gt;很普通，就不在公布代码了&lt;/p&gt;&#xD;
&lt;p&gt;3.&lt;/p&gt;&#xD;
&lt;p&gt;完成这些工作之后&lt;/p&gt;&#xD;
&lt;p&gt;我们只要在客户端构造好表单&lt;/p&gt;&#xD;
&lt;p&gt;然后把表单POST到指定的路径&lt;/p&gt;&#xD;
&lt;p&gt;就能完成服务的访问了！&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;---------------------------------------------------------------&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;喜欢的话~请大家推荐我的文章&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;谢谢~&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;我真的很需要你们的支持&lt;/strong&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/liulun/aggbug/2313674.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/liulun/archive/2012/01/05/2313674.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/liulun/archive/2012/01/04/2312482.html</id><title type="text">SilverLight企业应用框架设计【二】框架画面</title><summary type="text">框架画面分为上中下三层 由下面一个Grid控件完成布局 &amp;lt;Grid x:Name=&amp;quot;LayoutRoot&amp;quot;&amp;gt; &amp;lt;Grid.RowDefinitions&amp;gt; &amp;lt;RowDefinition Height=&amp;quot;60&amp;quot;&amp;gt;&amp;lt;/RowDefinition&amp;gt; &amp;lt;RowDefinition Height=&amp;quot;*&amp;quot;&amp;gt;&amp;lt;/RowDefinition&amp;gt; ...</summary><published>2012-01-04T13:31:00Z</published><updated>2012-01-04T13:31:00Z</updated><author><name>liulun</name><uri>http://www.cnblogs.com/liulun/</uri></author><link rel="alternate" href="http://www.cnblogs.com/liulun/archive/2012/01/04/2312482.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/liulun/archive/2012/01/04/2312482.html"/><content type="html">&lt;p&gt;框架画面分为上中下三层&lt;/p&gt; &lt;p&gt;由下面一个Grid控件完成布局&lt;/p&gt; &lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b"&gt;&lt;pre&gt;&amp;lt;Grid x:Name="LayoutRoot"&amp;gt;&#xD;
        &amp;lt;Grid.RowDefinitions&amp;gt;&#xD;
            &amp;lt;RowDefinition Height="60"&amp;gt;&amp;lt;/RowDefinition&amp;gt;&#xD;
            &amp;lt;RowDefinition Height="*"&amp;gt;&amp;lt;/RowDefinition&amp;gt;&#xD;
            &amp;lt;RowDefinition Height="22"&amp;gt;&amp;lt;/RowDefinition&amp;gt;&#xD;
        &amp;lt;/Grid.RowDefinitions&amp;gt;&#xD;
       &amp;lt;/Grid&amp;gt;&lt;/pre&gt;&#xD;
&lt;div&gt;&lt;/div&gt;&lt;/fieldset&gt; &#xD;
&lt;p&gt;上层为顶部菜单区域&lt;/p&gt;&#xD;
&lt;p&gt;中层为子菜单和业务画面部分&lt;/p&gt;&#xD;
&lt;p&gt;下层为状态栏和版权信息区域&lt;/p&gt;&#xD;
&lt;p&gt;&lt;img src="http://images.cnblogs.com/cnblogs_com/liulun/201201/201201031623462922.png"&gt;&lt;/p&gt;&#xD;
&lt;p&gt;下面我们分别看一下这三个部分的生成逻辑&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font color="#ff0000"&gt;&lt;strong&gt;一：顶部菜单区域&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;XAML代码如下：&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b"&gt;&lt;pre&gt;&amp;lt;StackPanel x:Name="TopMenuS" Orientation="Horizontal" Background="{StaticResource HeadBG}"&amp;gt;&#xD;
            &amp;lt;Grid&amp;gt;&#xD;
                &amp;lt;Grid.ColumnDefinitions&amp;gt;&#xD;
                    &amp;lt;ColumnDefinition Width="10"&amp;gt;&amp;lt;/ColumnDefinition&amp;gt;&#xD;
                    &amp;lt;ColumnDefinition Width="142"&amp;gt;&amp;lt;/ColumnDefinition&amp;gt;&#xD;
                    &amp;lt;ColumnDefinition Width="10"&amp;gt;&amp;lt;/ColumnDefinition&amp;gt;&#xD;
                &amp;lt;/Grid.ColumnDefinitions&amp;gt;&#xD;
                &amp;lt;Grid.RowDefinitions&amp;gt;&#xD;
                    &amp;lt;RowDefinition Height="3"&amp;gt;&amp;lt;/RowDefinition&amp;gt;&#xD;
                    &amp;lt;RowDefinition Height="18"&amp;gt;&amp;lt;/RowDefinition&amp;gt;&#xD;
                    &amp;lt;RowDefinition Height="18"&amp;gt;&amp;lt;/RowDefinition&amp;gt;&#xD;
                    &amp;lt;RowDefinition Height="18"&amp;gt;&amp;lt;/RowDefinition&amp;gt;&#xD;
                    &amp;lt;RowDefinition Height="3"&amp;gt;&amp;lt;/RowDefinition&amp;gt;&#xD;
                &amp;lt;/Grid.RowDefinitions&amp;gt;&#xD;
                &amp;lt;TextBlock x:Name="helloBlock" Grid.Column="1" Grid.Row="1" Text="xxxx通信" /&amp;gt;&#xD;
                &amp;lt;TextBlock x:Name="UserName" Text="Administrator" Grid.Column="1" Grid.Row="2" /&amp;gt;&#xD;
                &amp;lt;TextBlock Text="欢迎使用 xxx监控系统" Grid.Column="1" Grid.Row="3" /&amp;gt;&#xD;
            &amp;lt;/Grid&amp;gt;&#xD;
            &amp;lt;Rectangle Width="1" Fill="{StaticResource HeadSplitor}"&amp;gt;&amp;lt;/Rectangle&amp;gt;                        &#xD;
            &amp;lt;StackPanel&amp;gt;&#xD;
                &amp;lt;Button Style="{StaticResource ToolBtnStyle}" Content="全部关闭" Click="CloseAllClick"&amp;gt;&amp;lt;/Button&amp;gt;&#xD;
                &amp;lt;Button Style="{StaticResource ToolBtnStyle}" Content="关闭当前" Click="CloseCurClick"&amp;gt;&amp;lt;/Button&amp;gt;&#xD;
                &amp;lt;Button Style="{StaticResource ToolBtnStyle}" Content="关闭其他" Click="CloseOtherClick"&amp;gt;&amp;lt;/Button&amp;gt;&#xD;
            &amp;lt;/StackPanel&amp;gt;&#xD;
            &amp;lt;Rectangle Width="1" Fill="{StaticResource HeadSplitor}"&amp;gt;&amp;lt;/Rectangle&amp;gt;&#xD;
            &amp;lt;StackPanel&amp;gt;&#xD;
                &amp;lt;Button Style="{StaticResource ToolBtnStyle}" Content="修改密码" Click="ChangePSWBtnClick"&amp;gt;&amp;lt;/Button&amp;gt;&#xD;
                &amp;lt;Button Style="{StaticResource ToolBtnStyle}" Content="退出系统" Click="LoginOutBtnClick"&amp;gt;&amp;lt;/Button&amp;gt;&#xD;
                &amp;lt;Button Style="{StaticResource ToolBtnStyle}" Content="重新登录" Click="ReLoginBtnClick"&amp;gt;&amp;lt;/Button&amp;gt;&#xD;
            &amp;lt;/StackPanel&amp;gt;&#xD;
            &amp;lt;Rectangle Width="1" Fill="{StaticResource HeadSplitor}"&amp;gt;&amp;lt;/Rectangle&amp;gt;&#xD;
        &amp;lt;/StackPanel&amp;gt;&lt;/pre&gt;&#xD;
&lt;div&gt;&lt;/div&gt;&lt;/fieldset&gt;&#xD;
&lt;p&gt;顶部菜单分为三部分&lt;/p&gt;&#xD;
&lt;p&gt;从左向右依次是&lt;/p&gt;&#xD;
&lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&#xD;
&lt;p&gt;&lt;font color="#000000"&gt;欢迎信息（GRID）&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font color="#000000"&gt;顶部菜单（动态创建）&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font color="#000000"&gt;常用按钮（StackPanel)&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt;&#xD;
&lt;p&gt;&lt;font color="#000000"&gt;顶部菜单的容器是一个StackPanel&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;此容器有一个渐变的背景色，样式代码如下&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b"&gt;&lt;pre&gt;&amp;lt;!--头部渐变背景--&amp;gt;&#xD;
    &amp;lt;LinearGradientBrush x:Key="HeadBG" StartPoint="0.5 0" EndPoint="0.5 1"&amp;gt;&#xD;
        &amp;lt;GradientStop Offset="0" Color="#FAFAFA"&amp;gt;&amp;lt;/GradientStop&amp;gt;&#xD;
        &amp;lt;GradientStop Offset="0.5" Color="#D6D6D6"&amp;gt;&amp;lt;/GradientStop&amp;gt;&#xD;
    &amp;lt;/LinearGradientBrush&amp;gt;&lt;/pre&gt;&#xD;
&lt;div&gt;&lt;/div&gt;&lt;/fieldset&gt;&#xD;
&lt;p&gt;此容器每个部分都有一个Rectangle来分割&lt;/p&gt;&#xD;
&lt;p&gt;此Rectangle也有个渐变的背景，代码如下&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b"&gt;&lt;pre&gt;&amp;lt;!--头部分隔条渐变背景--&amp;gt;&#xD;
    &amp;lt;LinearGradientBrush x:Key="HeadSplitor" StartPoint="0.5 0" EndPoint="0.5 1"&amp;gt;&#xD;
        &amp;lt;GradientStop Offset="0" Color="#FAFAFA"&amp;gt;&amp;lt;/GradientStop&amp;gt;&#xD;
        &amp;lt;GradientStop Offset="1" Color="#000000"&amp;gt;&amp;lt;/GradientStop&amp;gt;&#xD;
    &amp;lt;/LinearGradientBrush&amp;gt;&lt;/pre&gt;&#xD;
&lt;div&gt;&lt;/div&gt;&lt;/fieldset&gt;&#xD;
&lt;p&gt;常用按钮的样式如下：&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b"&gt;&lt;pre&gt;&amp;lt;!--头部的 三分栏  工具按钮样式--&amp;gt;&#xD;
    &amp;lt;Style x:Key="ToolBtnStyle" TargetType="Button"&amp;gt;&#xD;
        &amp;lt;Style.Setters&amp;gt;&#xD;
            &amp;lt;Setter Property="Width" Value="90"&amp;gt;&amp;lt;/Setter&amp;gt;&#xD;
            &amp;lt;Setter Property="Height" Value="20"&amp;gt;&amp;lt;/Setter&amp;gt;&#xD;
            &amp;lt;Setter Property="Cursor" Value="Hand"&amp;gt;&amp;lt;/Setter&amp;gt;&#xD;
            &amp;lt;Setter Property="Template"&amp;gt;&#xD;
                &amp;lt;Setter.Value&amp;gt;&#xD;
                    &amp;lt;ControlTemplate TargetType="Button"&amp;gt;&#xD;
                        &amp;lt;Grid x:Name="Container"&amp;gt;&#xD;
                            &amp;lt;vsm:VisualStateManager.VisualStateGroups&amp;gt;&#xD;
                                &amp;lt;vsm:VisualStateGroup x:Name="CommonStates"&amp;gt;&#xD;
                                    &amp;lt;vsm:VisualState x:Name="MouseOver"&amp;gt;&#xD;
                                        &amp;lt;Storyboard&amp;gt;&#xD;
                                            &amp;lt;DoubleAnimation Storyboard.TargetName="fillColor" Storyboard.TargetProperty="Opacity" Duration="0" To="1"/&amp;gt;&#xD;
                                        &amp;lt;/Storyboard&amp;gt;&#xD;
                                    &amp;lt;/vsm:VisualState&amp;gt;&#xD;
                                    &amp;lt;vsm:VisualState x:Name="Normal" /&amp;gt;&#xD;
                                &amp;lt;/vsm:VisualStateGroup&amp;gt;&#xD;
                            &amp;lt;/vsm:VisualStateManager.VisualStateGroups&amp;gt;&#xD;
                            &amp;lt;Rectangle x:Name="fillColor" Opacity="0" Fill="#B5B5B5"  IsHitTestVisible="False" RadiusX="1" RadiusY="1"/&amp;gt;&#xD;
                            &amp;lt;ContentPresenter                                &#xD;
    			                x:Name="contentPresenter"&#xD;
    			                Content="{TemplateBinding Content}"&#xD;
    			                ContentTemplate="{TemplateBinding ContentTemplate}"&#xD;
    			                VerticalAlignment="{TemplateBinding VerticalContentAlignment}"&#xD;
    			                HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"&#xD;
    			                Margin="{TemplateBinding Padding}"/&amp;gt;&#xD;
                        &amp;lt;/Grid&amp;gt;&#xD;
                    &amp;lt;/ControlTemplate&amp;gt;&#xD;
                &amp;lt;/Setter.Value&amp;gt;&#xD;
            &amp;lt;/Setter&amp;gt;&#xD;
        &amp;lt;/Style.Setters&amp;gt;&#xD;
    &amp;lt;/Style&amp;gt;&lt;/pre&gt;&#xD;
&lt;div&gt;&lt;/div&gt;&lt;/fieldset&gt;&#xD;
&lt;p&gt;动态创建顶部菜单的代码如下&lt;/p&gt;&#xD;
&lt;p&gt;（&lt;em&gt;大家先不要深究数据是怎么来的，在以后的章节咱们会讲到数据交互的细节&lt;/em&gt;）&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b"&gt;&lt;pre&gt;var tops = Common.ViewUtility.AllMenu&#xD;
                .Where(m =&amp;gt; m.ParentId == Guid.Empty)&#xD;
                .OrderByDescending(m =&amp;gt; m.MenuOrder);&#xD;
            foreach (var m in tops)&#xD;
            {&#xD;
                var topM = new HeadBtn();&#xD;
                topM.DataContext = m;&#xD;
                topM.MouseLeftButtonUp += new MouseButtonEventHandler(topM_MouseLeftButtonUp);&#xD;
                TopMenuS.Children.Insert(2,topM);&#xD;
            }&lt;/pre&gt;&#xD;
&lt;div&gt;&lt;/div&gt;&lt;/fieldset&gt;&#xD;
&lt;p&gt;这里创建的HeadBtn是一个自定义的控件&lt;/p&gt;&#xD;
&lt;p&gt;（每个顶部菜单就是一个控件的实例）&lt;/p&gt;&#xD;
&lt;p&gt;该自定义控件XAML代码如下：&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b"&gt;&lt;pre&gt;&amp;lt;StackPanel Orientation="Horizontal" Cursor="Hand"&amp;gt;&#xD;
        &amp;lt;Grid x:Name="btn" Width="90" Height="60"&amp;gt;&#xD;
            &amp;lt;Grid.RowDefinitions&amp;gt;&#xD;
                &amp;lt;RowDefinition&amp;gt;&amp;lt;/RowDefinition&amp;gt;&#xD;
                &amp;lt;RowDefinition Height="20"&amp;gt;&amp;lt;/RowDefinition&amp;gt;&#xD;
            &amp;lt;/Grid.RowDefinitions&amp;gt;&#xD;
            &amp;lt;Image Source="../Images/module2.png" Height="30"&amp;gt;&amp;lt;/Image&amp;gt;&#xD;
            &amp;lt;TextBlock Text="{Binding MenuName}" Grid.Row="1" FontSize="12"&#xD;
                       VerticalAlignment="Center" HorizontalAlignment="Center" &amp;gt;&amp;lt;/TextBlock&amp;gt;&#xD;
        &amp;lt;/Grid&amp;gt;&#xD;
        &amp;lt;Rectangle Width="1" Fill="{StaticResource HeadSplitor}"&amp;gt;&amp;lt;/Rectangle&amp;gt;&#xD;
    &amp;lt;/StackPanel&amp;gt;&lt;/pre&gt;&#xD;
&lt;div&gt;&lt;/div&gt;&lt;/fieldset&gt;&#xD;
&lt;p&gt;注意，这里每个顶部菜单的ICO图标不是动态的，朋友们，想让他变成动态的就自己动手吧&lt;/p&gt;&#xD;
&lt;p&gt;为了实现美观的效果&lt;/p&gt;&#xD;
&lt;p&gt;我为这个自定义控件定义了鼠标的滑入滑出事件&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b"&gt;&lt;pre&gt;private void UserControl_MouseEnter(object sender, MouseEventArgs e)&#xD;
        {&#xD;
            var color = Color.FromArgb(255,180, 180, 180);&#xD;
            btn.Background = new SolidColorBrush(color);&#xD;
        }&#xD;
        private void UserControl_MouseLeave(object sender, MouseEventArgs e)&#xD;
        {&#xD;
            btn.Background = new SolidColorBrush(Colors.Transparent);&#xD;
        }&lt;/pre&gt;&#xD;
&lt;div&gt;&lt;/div&gt;&lt;/fieldset&gt;&#xD;
&lt;p&gt;这些颜色的值，本应该作为资源放在样式文件中，我这里也没有做处理&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;font color="#ff0000"&gt;二：底部状态条区域&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;此处比较简单&lt;/p&gt;&#xD;
&lt;p&gt;代码如下：&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b"&gt;&lt;pre&gt;&amp;lt;StackPanel Width="Auto" Grid.Row="2" &#xD;
                    Background="#B5B5B5" Orientation="Horizontal" FlowDirection="RightToLeft"&amp;gt;&#xD;
            &amp;lt;TextBlock VerticalAlignment="Center" Text="V1.0.0 Copy Right © All Rights Reserved"/&amp;gt;&#xD;
            &amp;lt;TextBlock VerticalAlignment="Center"  Text="xxxx"/&amp;gt;&#xD;
        &amp;lt;/StackPanel&amp;gt;&lt;/pre&gt;&#xD;
&lt;div&gt;&lt;/div&gt;&lt;/fieldset&gt;&#xD;
&lt;p&gt;1.我没有做状态信息的内容&lt;/p&gt;&#xD;
&lt;p&gt;2.版本信息应该通过Assambly获取&lt;/p&gt;&#xD;
&lt;p&gt;&lt;font color="#ff0000"&gt;&lt;strong&gt;三：中部区域&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&#xD;
&lt;p&gt;XAML代码如下&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b"&gt;&lt;pre&gt;&amp;lt;Border  Grid.Row="1" BorderBrush="#B5B5B5" BorderThickness="0 1 0 0"&amp;gt;&#xD;
            &amp;lt;Grid  Background="#E8E8E8" Margin="0 1 0 0" Name="CenterGrid"&amp;gt;&#xD;
                &amp;lt;Grid.ColumnDefinitions&amp;gt;&#xD;
                    &amp;lt;ColumnDefinition Width="160"&amp;gt;&amp;lt;/ColumnDefinition&amp;gt;&#xD;
                    &amp;lt;ColumnDefinition Width="*"&amp;gt;&amp;lt;/ColumnDefinition&amp;gt;&#xD;
                &amp;lt;/Grid.ColumnDefinitions&amp;gt;&#xD;
                &amp;lt;StackPanel&amp;gt;&#xD;
                    &amp;lt;sdk:Label  Height="26"  Background="#b5b5b5"  Margin="0 6 0 6"&#xD;
                                FontWeight="Bold" FontSize="12" x:Name="lblMenuText" &#xD;
                                HorizontalAlignment="Center"  Width="160"  /&amp;gt;&#xD;
                    &amp;lt;ListBox  SelectionChanged="left_panel_SelectionChanged"  &#xD;
                               ItemContainerStyle="{StaticResource ListBoxItemStyleNew}"&#xD;
                               Grid.Column="0" x:Name="left_panel" Background="#E8E8E8" BorderThickness="0"&amp;gt;&#xD;
                        &amp;lt;ListBox.ItemTemplate&amp;gt;&#xD;
                            &amp;lt;DataTemplate&amp;gt;&#xD;
                                &amp;lt;ContentPresenter Content="{Binding MenuName}"&amp;gt;&amp;lt;/ContentPresenter&amp;gt;&#xD;
                            &amp;lt;/DataTemplate&amp;gt;&#xD;
                        &amp;lt;/ListBox.ItemTemplate&amp;gt;&#xD;
                    &amp;lt;/ListBox&amp;gt;&#xD;
                &amp;lt;/StackPanel&amp;gt;&#xD;
                &amp;lt;sdk:TabControl x:Name="tbControl" SelectionChanged="tbControl_SelectionChanged" Grid.Column="1" Margin="0 6 0 0"&amp;gt;&#xD;
                &amp;lt;/sdk:TabControl&amp;gt;&#xD;
            &amp;lt;/Grid&amp;gt;&#xD;
        &amp;lt;/Border&amp;gt;&lt;/pre&gt;&#xD;
&lt;div&gt;&lt;/div&gt;&lt;/fieldset&gt;&#xD;
&lt;p&gt;其中Label控件显示的为顶部菜单的标题，标志着当前选中的是哪个顶部菜单&lt;/p&gt;&#xD;
&lt;p&gt;ListBox为子菜单控件&lt;/p&gt;&#xD;
&lt;p&gt;TabControl为业务画面区域&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;font color="#ff0000"&gt;四：子菜单区域&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;子菜单样式相对复杂些&lt;/p&gt;&#xD;
&lt;p&gt;样式代码如下&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b"&gt;&lt;pre&gt;&amp;lt;!--子菜单样式--&amp;gt;&#xD;
    &amp;lt;Style TargetType="ListBoxItem" x:Key="ListBoxItemStyleNew" &amp;gt;&#xD;
        &amp;lt;Setter Property="Padding" Value="3" /&amp;gt;&#xD;
        &amp;lt;Setter Property="HorizontalContentAlignment" Value="Center" /&amp;gt;&#xD;
        &amp;lt;Setter Property="VerticalContentAlignment" Value="Center" /&amp;gt;&#xD;
        &amp;lt;Setter Property="Background" Value="Transparent" /&amp;gt;&#xD;
        &amp;lt;Setter Property="BorderThickness" Value="1"/&amp;gt;&#xD;
        &amp;lt;Setter Property="TabNavigation" Value="Local" /&amp;gt;&#xD;
        &amp;lt;Setter Property="Template"&amp;gt;&#xD;
            &amp;lt;Setter.Value&amp;gt;&#xD;
                &amp;lt;ControlTemplate TargetType="ListBoxItem"&amp;gt;&#xD;
                    &amp;lt;Grid Background="{TemplateBinding Background}"&amp;gt;&#xD;
                        &amp;lt;vsm:VisualStateManager.VisualStateGroups&amp;gt;&#xD;
                            &amp;lt;vsm:VisualStateGroup x:Name="CommonStates"&amp;gt;&#xD;
                                &amp;lt;vsm:VisualState x:Name="Normal" /&amp;gt;&#xD;
                                &amp;lt;vsm:VisualState x:Name="MouseOver"&amp;gt;&#xD;
                                    &amp;lt;Storyboard&amp;gt;&#xD;
                                        &amp;lt;DoubleAnimation Storyboard.TargetName="fillColor" Storyboard.TargetProperty="Opacity" Duration="0" To=".35"/&amp;gt;&#xD;
                                    &amp;lt;/Storyboard&amp;gt;&#xD;
                                &amp;lt;/vsm:VisualState&amp;gt;&#xD;
                                &amp;lt;vsm:VisualState x:Name="Disabled"&amp;gt;&#xD;
                                    &amp;lt;Storyboard&amp;gt;&#xD;
                                        &amp;lt;DoubleAnimation Storyboard.TargetName="contentPresenter" Storyboard.TargetProperty="Opacity" Duration="0" To=".55" /&amp;gt;&#xD;
                                    &amp;lt;/Storyboard&amp;gt;&#xD;
                                &amp;lt;/vsm:VisualState&amp;gt;&#xD;
                            &amp;lt;/vsm:VisualStateGroup&amp;gt;&#xD;
                            &amp;lt;vsm:VisualStateGroup x:Name="SelectionStates"&amp;gt;&#xD;
                                &amp;lt;vsm:VisualState x:Name="Unselected" /&amp;gt;&#xD;
                                &amp;lt;vsm:VisualState x:Name="Selected"&amp;gt;&#xD;
                                    &amp;lt;Storyboard&amp;gt;&#xD;
                                        &amp;lt;DoubleAnimation Storyboard.TargetName="fillColor2" Storyboard.TargetProperty="Opacity" Duration="0" To=".75"/&amp;gt;&#xD;
                                    &amp;lt;/Storyboard&amp;gt;&#xD;
                                &amp;lt;/vsm:VisualState&amp;gt;&#xD;
                            &amp;lt;/vsm:VisualStateGroup&amp;gt;&#xD;
                            &amp;lt;vsm:VisualStateGroup x:Name="FocusStates"&amp;gt;&#xD;
                                &amp;lt;vsm:VisualState x:Name="Focused"&amp;gt;&#xD;
                                    &amp;lt;Storyboard&amp;gt;&#xD;
                                        &amp;lt;ObjectAnimationUsingKeyFrames Storyboard.TargetName="FocusVisualElement" Storyboard.TargetProperty="Visibility" Duration="0"&amp;gt;&#xD;
                                            &amp;lt;DiscreteObjectKeyFrame KeyTime="0"&amp;gt;&#xD;
                                                &amp;lt;DiscreteObjectKeyFrame.Value&amp;gt;&#xD;
                                                    &amp;lt;Visibility&amp;gt;Visible&amp;lt;/Visibility&amp;gt;&#xD;
                                                &amp;lt;/DiscreteObjectKeyFrame.Value&amp;gt;&#xD;
                                            &amp;lt;/DiscreteObjectKeyFrame&amp;gt;&#xD;
                                        &amp;lt;/ObjectAnimationUsingKeyFrames&amp;gt;&#xD;
                                    &amp;lt;/Storyboard&amp;gt;&#xD;
                                &amp;lt;/vsm:VisualState&amp;gt;&#xD;
                                &amp;lt;vsm:VisualState x:Name="Unfocused"/&amp;gt;&#xD;
                            &amp;lt;/vsm:VisualStateGroup&amp;gt;&#xD;
                        &amp;lt;/vsm:VisualStateManager.VisualStateGroups&amp;gt;&#xD;
                        &amp;lt;Rectangle x:Name="fillColor" Opacity="0" Fill="#B5B5B5"  IsHitTestVisible="False" RadiusX="1" RadiusY="1"/&amp;gt;&#xD;
                        &amp;lt;Rectangle x:Name="fillColor2" Opacity="0" Fill="#FFBADDE9" IsHitTestVisible="False" RadiusX="1" RadiusY="1"/&amp;gt;&#xD;
                        &amp;lt;ContentPresenter&#xD;
                              x:Name="contentPresenter"&#xD;
                                Cursor="Hand"&#xD;
                              Content="{TemplateBinding Content}"&#xD;
                              ContentTemplate="{TemplateBinding ContentTemplate}"&#xD;
                              HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"&#xD;
                              Margin="{TemplateBinding Padding}"/&amp;gt;&#xD;
                        &amp;lt;Rectangle x:Name="FocusVisualElement" Stroke="#FF6DBDD1" StrokeThickness="1" Visibility="Collapsed" RadiusX="1" RadiusY="1" /&amp;gt;&#xD;
                    &amp;lt;/Grid&amp;gt;&#xD;
                &amp;lt;/ControlTemplate&amp;gt;&#xD;
            &amp;lt;/Setter.Value&amp;gt;&#xD;
        &amp;lt;/Setter&amp;gt;&#xD;
    &amp;lt;/Style&amp;gt;&lt;/pre&gt;&#xD;
&lt;div&gt;&lt;/div&gt;&lt;/fieldset&gt;&#xD;
&lt;p&gt;这些样式主要是为了实现如下效果&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/liulun/201201/201201042131183323.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/liulun/201201/201201042131202319.png" width="168" height="244"&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;子菜单数据绑定非常简单&lt;/p&gt;&#xD;
&lt;p&gt;（顶部菜单的单击事件将绑定子菜单）&lt;/p&gt;&#xD;
&lt;p&gt;代码如下：&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b"&gt;&lt;pre&gt;void topM_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)&#xD;
        {&#xD;
            var tBTN = sender as HeadBtn;&#xD;
            var tMenu = tBTN.DataContext as MenuM;&#xD;
            lblMenuText.Content = tMenu.MenuName;&#xD;
            var subs = Common.ViewUtility.AllMenu&#xD;
                .Where(m =&amp;gt; m.ParentId == tMenu.Id)&#xD;
                .OrderBy(m =&amp;gt; m.MenuOrder);&#xD;
            left_panel.ItemsSource = subs;&#xD;
        }&lt;/pre&gt;&#xD;
&lt;div&gt;&lt;/div&gt;&lt;/fieldset&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;font color="#ff0000"&gt;五：业务画面区域&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;业务画面的容器为TabControl&lt;/p&gt;&#xD;
&lt;p&gt;每个TabItem将承载一个业务画面&lt;/p&gt;&#xD;
&lt;p&gt;主要是为TabItem增加关闭按钮&lt;/p&gt;&#xD;
&lt;p&gt;XAML代码如下：&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b"&gt;&lt;pre&gt;&amp;lt;sdk:TabItem.HeaderTemplate&amp;gt;&#xD;
        &amp;lt;DataTemplate&amp;gt;&#xD;
            &amp;lt;StackPanel Orientation="Horizontal" Width="auto" Margin="0 0 -2 -2"&amp;gt;&#xD;
                &amp;lt;TextBlock  x:Name="tboxheader" Text="{Binding}"/&amp;gt;&#xD;
                &amp;lt;Button Cursor="Hand" Click="CloseBTN_Click" Style="{StaticResource ListViewHeadBtnStyle}" Margin="3,-3,-6,0"  Content="X" &amp;gt;&#xD;
                &amp;lt;/Button&amp;gt;&#xD;
            &amp;lt;/StackPanel&amp;gt;&#xD;
        &amp;lt;/DataTemplate&amp;gt;&#xD;
    &amp;lt;/sdk:TabItem.HeaderTemplate&amp;gt;&#xD;
    &amp;lt;/sdk:TabItem&amp;gt;&lt;/pre&gt;&#xD;
&lt;div&gt;&lt;/div&gt;&lt;/fieldset&gt;&#xD;
&lt;p&gt;这个关闭按钮的样式比较特殊&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b"&gt;&lt;pre&gt;&amp;lt;!--标签按钮--&amp;gt;&#xD;
    &amp;lt;Style x:Key="ListViewHeadBtnStyle" TargetType="Button"&amp;gt;&#xD;
        &amp;lt;Style.Setters&amp;gt;&#xD;
            &amp;lt;Setter Property="Width" Value="20"&amp;gt;&amp;lt;/Setter&amp;gt;&#xD;
            &amp;lt;Setter Property="Height" Value="20"&amp;gt;&amp;lt;/Setter&amp;gt;&#xD;
            &amp;lt;Setter Property="Template"&amp;gt;&#xD;
                &amp;lt;Setter.Value&amp;gt;&#xD;
                    &amp;lt;ControlTemplate TargetType="Button"&amp;gt;&#xD;
                        &amp;lt;Grid  x:Name="Container"&amp;gt;&#xD;
                            &amp;lt;vsm:VisualStateManager.VisualStateGroups&amp;gt;&#xD;
                                &amp;lt;vsm:VisualStateGroup x:Name="CommonStates"&amp;gt;&#xD;
                                    &amp;lt;vsm:VisualState x:Name="Normal" /&amp;gt;&#xD;
                                    &amp;lt;vsm:VisualState x:Name="MouseOver"&amp;gt;&#xD;
                                        &amp;lt;Storyboard&amp;gt;&#xD;
                                            &amp;lt;DoubleAnimation Storyboard.TargetName="fillColor" Storyboard.TargetProperty="Opacity" Duration="0" To=".35"/&amp;gt;&#xD;
                                        &amp;lt;/Storyboard&amp;gt;&#xD;
                                    &amp;lt;/vsm:VisualState&amp;gt;&#xD;
                                &amp;lt;/vsm:VisualStateGroup&amp;gt;&#xD;
                            &amp;lt;/vsm:VisualStateManager.VisualStateGroups&amp;gt;&#xD;
                            &amp;lt;Rectangle x:Name="fillColor" Opacity="0" Fill="#B5B5B5"  IsHitTestVisible="False" RadiusX="1" RadiusY="1"/&amp;gt;&#xD;
                            &amp;lt;ContentPresenter                                &#xD;
    			                x:Name="contentPresenter"&#xD;
    			                Content="{TemplateBinding Content}"&#xD;
    			                ContentTemplate="{TemplateBinding ContentTemplate}"&#xD;
    			                VerticalAlignment="{TemplateBinding VerticalContentAlignment}"&#xD;
    			                HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"&#xD;
    			                Margin="{TemplateBinding Padding}"/&amp;gt;&#xD;
                        &amp;lt;/Grid&amp;gt;&#xD;
                    &amp;lt;/ControlTemplate&amp;gt;&#xD;
                &amp;lt;/Setter.Value&amp;gt;&#xD;
            &amp;lt;/Setter&amp;gt;&#xD;
        &amp;lt;/Style.Setters&amp;gt;&#xD;
    &amp;lt;/Style&amp;gt;&lt;/pre&gt;&#xD;
&lt;div&gt;&lt;/div&gt;&lt;/fieldset&gt;&#xD;
&lt;p&gt;关闭按钮样式主要为了实现如下效果&lt;/p&gt;&#xD;
&lt;p&gt;（鼠标滑上，关闭按钮背景变灰色）&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/liulun/201201/20120104213120617.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/liulun/201201/20120104213123286.png" width="216" height="71"&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;按钮的单击事件如下&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b"&gt;&lt;pre&gt;private void CloseBTN_Click(object sender, RoutedEventArgs e)&#xD;
        {&#xD;
            var tc = this.Parent as TabControl;&#xD;
            tc.Items.Remove(this);&#xD;
        }&lt;/pre&gt;&#xD;
&lt;div&gt;&lt;/div&gt;&lt;/fieldset&gt;&lt;img src="http://www.cnblogs.com/liulun/aggbug/2312482.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/liulun/archive/2012/01/04/2312482.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/liulun/archive/2012/01/03/2311072.html</id><title type="text">SilverLight企业应用框架设计【一】整体说明</title><summary type="text">闲言碎语~不要讲先上图片这个系列讲到的这个系统与WinForm企业应用框架设计【一】界限划分与动态创建WCF服务（no svc!no serviceActivations!）WinForm企业应用框架设计【二】团队内部的约定和客户端按约定识别WCF服务WinForm企业应用框架设计【三】框架窗体设计；动态创建菜单；WinForm企业应用框架设计【四】动态创建业务窗体WinForm企业应用框架设计【五】系统登录以及身份验证+源码这个系列类似只不过是用在silverlight上的当然，换了平台就换了很多技术下面我说一下这个框架的一些特点一：自己实现基于HTTP的REST服务用siliverligh</summary><published>2012-01-03T08:24:00Z</published><updated>2012-01-03T08:24:00Z</updated><author><name>liulun</name><uri>http://www.cnblogs.com/liulun/</uri></author><link rel="alternate" href="http://www.cnblogs.com/liulun/archive/2012/01/03/2311072.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/liulun/archive/2012/01/03/2311072.html"/><content type="html">&lt;p&gt;闲言碎语~不要讲&lt;/p&gt;&#xD;
&lt;p&gt;先上图片&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/liulun/201201/201201031623456892.png"&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" title="image" src="http://images.cnblogs.com/cnblogs_com/liulun/201201/201201031623462922.png" alt="image" width="678" height="420" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;这个系列讲到的这个系统与&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://www.cnblogs.com/liulun/archive/2011/11/29/2268337.html"&gt;WinForm企业应用框架设计【一】界限划分与动态创建WCF服务（no svc!no serviceActivations!）&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://www.cnblogs.com/liulun/archive/2011/11/30/2269602.html"&gt;WinForm企业应用框架设计【二】团队内部的约定和客户端按约定识别WCF服务&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://www.cnblogs.com/liulun/archive/2011/12/04/2275097.html"&gt;WinForm企业应用框架设计【三】框架窗体设计；动态创建菜单；&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://www.cnblogs.com/liulun/archive/2011/12/08/2280110.html"&gt;WinForm企业应用框架设计【四】动态创建业务窗体&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://www.cnblogs.com/liulun/archive/2011/12/16/2290800.html"&gt;WinForm企业应用框架设计【五】系统登录以及身份验证+源码&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;这个系列类似&lt;/p&gt;&#xD;
&lt;p&gt;只不过是用在silverlight上的&lt;/p&gt;&#xD;
&lt;p&gt;当然，换了平台就换了很多技术&lt;/p&gt;&#xD;
&lt;p&gt;下面我说一下这个框架的一些特点&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="color: #ff0000;"&gt;一：自己实现基于HTTP的REST服务&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;用siliverlight开发企业应用&lt;/p&gt;&#xD;
&lt;p&gt;大多人数都喜欢用微软提供的EntityFramework + RIA Service&lt;/p&gt;&#xD;
&lt;p&gt;由于某些特殊的原因需要&lt;/p&gt;&#xD;
&lt;p&gt;项目可能不能用EF和RIAService&lt;/p&gt;&#xD;
&lt;p&gt;那么这个系列将为您提供一些指导和最佳实践原则&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="color: #ff0000;"&gt;二：自己实现客户端实体和服务代理的代码生成逻辑&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;使用RiaService的人肯定会知道&lt;/p&gt;&#xD;
&lt;p&gt;VS开发环境在Silverlight客户端&lt;/p&gt;&#xD;
&lt;p&gt;自动生成了服务代理的代码和实体的代码&lt;/p&gt;&#xD;
&lt;p&gt;这些代码放在&lt;/p&gt;&#xD;
&lt;p&gt;Generated_Code\[YorRIAService].g.cs&lt;/p&gt;&#xD;
&lt;p&gt;这个隐藏文件里&lt;/p&gt;&#xD;
&lt;p&gt;如果我们抛弃RIAService，&lt;/p&gt;&#xD;
&lt;p&gt;那么势必将自己完成这些代码生成工作&lt;/p&gt;&#xD;
&lt;p&gt;在我们这个系列中将介绍到&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;每次编译程序都会自动生成这些代码&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;的技巧&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="color: #ff0000;"&gt;三：自己实现的DataForm控件&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;Silverlight提供的DataForm控件用以编辑实体&lt;/p&gt;&#xD;
&lt;p&gt;非常强大&lt;/p&gt;&#xD;
&lt;p&gt;但是太过强大了，把一些操作搞他复杂了&lt;/p&gt;&#xD;
&lt;p&gt;咱们这个系列将使用自己的DataForm控件&lt;/p&gt;&#xD;
&lt;p&gt;完成实体编辑业务逻辑&lt;/p&gt;&#xD;
&lt;p&gt;-------------------------------------&lt;/p&gt;&#xD;
&lt;p&gt;还有其他的一些诸如&lt;/p&gt;&#xD;
&lt;p&gt;自定义tabcontrol模版的技巧&lt;/p&gt;&#xD;
&lt;p&gt;都会在这个系列中讲到&lt;/p&gt;&#xD;
&lt;p&gt;------------------------------------&lt;/p&gt;&#xD;
&lt;p&gt;本系列是使用SL4开发的&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;如果您感兴趣&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;那么就请推荐吧！&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;系列的最后&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;我会放出源码的！&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;谢谢大家了！&lt;/strong&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/liulun/aggbug/2311072.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/liulun/archive/2012/01/03/2311072.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/liulun/archive/2011/12/22/2298533.html</id><title type="text">DotNet4应用程序打包工具-&amp;gt;升级版【三】宿主程序分析+全部源码下载</title><summary type="text">索引DotNet4应用程序打包工具-&amp;gt;升级版【三】宿主程序分析+全部源码下载DotNet4应用程序打包工具-&amp;gt;升级版【二】安装工具分析DotNet4应用程序打包工具（把DotNet4安装程序打包进你的应用程序；WINAPI开发，无dotNet环境也可顺利执行）【一】整体思路废话少说入口函数入口函数是所有逻辑的集合体int WinMain(HINSTANCE hInstance,HINSTANCE hPreInstance,LPSTR lpCmdLine,int nCmdShow){	int result;	LPCTSTR netName = &amp;quot;.net4.exe&amp;quot</summary><published>2011-12-22T14:02:00Z</published><updated>2011-12-22T14:02:00Z</updated><author><name>liulun</name><uri>http://www.cnblogs.com/liulun/</uri></author><link rel="alternate" href="http://www.cnblogs.com/liulun/archive/2011/12/22/2298533.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/liulun/archive/2011/12/22/2298533.html"/><content type="html">&lt;p&gt;&lt;img src="http://images.cnblogs.com/cnblogs_com/liulun/201112/201112190721515572.png" alt="" width="504" height="248" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;索引&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a id="CategoryEntryList1_EntryStoryList_Entries_TitleUrl_0" href="http://www.cnblogs.com/liulun/archive/2011/12/22/2298533.html"&gt;DotNet4应用程序打包工具-&amp;gt;升级版【三】宿主程序分析+全部源码下载&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a id="CategoryEntryList1_EntryStoryList_Entries_TitleUrl_1" href="http://www.cnblogs.com/liulun/archive/2011/12/19/2292878.html"&gt;DotNet4应用程序打包工具-&amp;gt;升级版【二】安装工具分析&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a id="CategoryEntryList1_EntryStoryList_Entries_TitleUrl_2" href="http://www.cnblogs.com/liulun/archive/2011/12/12/2284360.html"&gt;DotNet4应用程序打包工具（把DotNet4安装程序打包进你的应用程序；WINAPI开发，无dotNet环境也可顺利执行）【一】整体思路&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;废话少说&lt;/p&gt;&#xD;
&lt;p&gt;入口函数&lt;/p&gt;&#xD;
&lt;p&gt;入口函数是所有逻辑的集合体&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b;"&gt;&#xD;
&lt;pre&gt;int WinMain(HINSTANCE hInstance,HINSTANCE hPreInstance,LPSTR lpCmdLine,int nCmdShow)&#xD;
{&#xD;
	int result;&#xD;
	LPCTSTR netName = ".net4.exe";&#xD;
	LPCTSTR tarName = ".tar.exe";&#xD;
	result = CheckDotNet4();&#xD;
	if(result == 0)&#xD;
	{		&#xD;
		result = FreeRC(MAKEINTRESOURCE(1012),netName);&#xD;
		if(result == 0)&#xD;
		{&#xD;
			Alert("没有成功释放预装工具~安装失败");&#xD;
			return 0;&#xD;
		}&#xD;
		result = CreateInstallProcess(netName);&#xD;
		if(result == 0)&#xD;
		{&#xD;
			Alert("没有成功启动预装工具进程~安装失败");&#xD;
			ClearFile(netName);&#xD;
			return 0;&#xD;
		}&#xD;
		//暂时不支持静默安装&#xD;
		//result = InstallIt();&#xD;
		result = CheckDotNet4();&#xD;
		if(result == 0)&#xD;
		{&#xD;
			Alert("没有成功安装预装工具~安装失败");&#xD;
			ClearFile(netName);&#xD;
			return 0;&#xD;
		}&#xD;
	}&#xD;
	result = FreeRC(MAKEINTRESOURCE(1001),tarName);&#xD;
	if(result == 0)&#xD;
	{&#xD;
		Alert("没有成功释放应用程序~安装失败");&#xD;
		ClearFile(netName);&#xD;
		ClearFile(tarName);&#xD;
		return 0;&#xD;
	}&#xD;
	result = CreateInstallProcess(tarName);&#xD;
	if(result == 0)&#xD;
	{&#xD;
		Alert("没有成功启动应用程序进程~安装失败");&#xD;
	}&#xD;
	ClearFile(netName);&#xD;
	ClearFile(tarName);&#xD;
	return 0;&#xD;
}&lt;/pre&gt;&#xD;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;&#xD;
&lt;/fieldset&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;判断目标环境是否有相关的注册表项&lt;/p&gt;&#xD;
&lt;p&gt;先从资源里提取出注册表项&lt;/p&gt;&#xD;
&lt;p&gt;然后判断&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b;"&gt;&#xD;
&lt;pre&gt;int CheckDotNet4()&#xD;
{&#xD;
	HMODULE hInstance = ::GetModuleHandle(NULL);&#xD;
    HRSRC hResID = ::FindResource(hInstance,MAKEINTRESOURCE(1039),RT_RCDATA); &#xD;
    HGLOBAL hRes = ::LoadResource(hInstance,hResID);&#xD;
    LPVOID pRes = ::LockResource(hRes);&#xD;
	DWORD dwResSize = ::SizeofResource(hInstance,hResID);&#xD;
	int length = MAX_PATH + 1;&#xD;
	if(!dwResSize) &#xD;
	{&#xD;
		return 0;&#xD;
	}&#xD;
	length = (int)dwResSize;&#xD;
	TCHAR  regeditStr[MAX_PATH + 1];&#xD;
	memcpy(regeditStr,pRes,dwResSize);&#xD;
	regeditStr[dwResSize] = 0;&#xD;
	HKEY ck;&#xD;
	int result = 1;&#xD;
	if(ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE,regeditStr,0,KEY_ALL_ACCESS,&amp;amp;ck))&#xD;
	{       &#xD;
		Alert("您的系统中缺少应用程序执行的环境\n现在开始为您搭建该环境");&#xD;
		result = 0;&#xD;
	}&#xD;
	RegCloseKey(ck);&#xD;
	return result;&#xD;
}&lt;/pre&gt;&#xD;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;&#xD;
&lt;/fieldset&gt;&#xD;
&lt;p&gt;如果没有相关的注册表项&lt;/p&gt;&#xD;
&lt;p&gt;就要释放出想要预先安装的程序&lt;/p&gt;&#xD;
&lt;p&gt;读取资源&lt;/p&gt;&#xD;
&lt;p&gt;并把资源写入文件&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b;"&gt;&#xD;
&lt;pre&gt;int FreeRC(LPCTSTR resourceID,LPCTSTR resourceName)&#xD;
{    &#xD;
    HMODULE hInstance = ::GetModuleHandle(NULL);&#xD;
	TCHAR  szFilePath[MAX_PATH + 1];&#xD;
	GetPath(szFilePath,resourceName,hInstance);&#xD;
    HRSRC hResID = ::FindResource(hInstance,resourceID,RT_RCDATA); &#xD;
    HGLOBAL hRes = ::LoadResource(hInstance,hResID);&#xD;
    LPVOID pRes = ::LockResource(hRes);&#xD;
    DWORD dwResSize = ::SizeofResource(hInstance,hResID);&#xD;
	if(!dwResSize)&#xD;
	{&#xD;
		return 0;&#xD;
	}&#xD;
    HANDLE hResFile = CreateFile(szFilePath,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);    &#xD;
    DWORD dwWritten = 0;&#xD;
    WriteFile(hResFile,pRes,dwResSize,&amp;amp;dwWritten,NULL);&#xD;
    CloseHandle(hResFile);&#xD;
    if(dwResSize == dwWritten);&#xD;
	{&#xD;
		return 1;&#xD;
	}&#xD;
	return 0;&#xD;
}&lt;/pre&gt;&#xD;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;&#xD;
&lt;/fieldset&gt;&#xD;
&lt;p&gt;成功释放之后&lt;/p&gt;&#xD;
&lt;p&gt;就执行这个程序&lt;/p&gt;&#xD;
&lt;p&gt;注意WaitForSingleObject的WINAPI&lt;/p&gt;&#xD;
&lt;p&gt;是等待进程退出&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b;"&gt;&#xD;
&lt;pre&gt;//创建进程&#xD;
int CreateInstallProcess(LPCTSTR resourceName)&#xD;
{&#xD;
	STARTUPINFO stinfo;&#xD;
	ZeroMemory((void*)&amp;amp;stinfo,sizeof(STARTUPINFO));&#xD;
	PROCESS_INFORMATION ProcessInfo;&#xD;
	stinfo.cb = sizeof(STARTUPINFO);&#xD;
	stinfo.dwFlags = STARTF_USESHOWWINDOW;&#xD;
	stinfo.wShowWindow = SW_SHOW;//SW_SHOW  SW_HIDE&#xD;
	TCHAR  szFilePath[MAX_PATH + 1];&#xD;
	GetPath(szFilePath,resourceName);//.dotnet4.exe&#xD;
	int result = CreateProcess(szFilePath,NULL,NULL,NULL,false,0,NULL,NULL,&amp;amp;stinfo,&amp;amp;ProcessInfo);&#xD;
	WaitForSingleObject(ProcessInfo.hProcess, INFINITE);&#xD;
	return result;        &#xD;
}&lt;/pre&gt;&#xD;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;&#xD;
&lt;/fieldset&gt;&#xD;
&lt;p&gt;如果进程没有被成功启动&lt;/p&gt;&#xD;
&lt;p&gt;就会删除释放的预安装程序&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b;"&gt;&#xD;
&lt;pre&gt;int ClearFile(LPCTSTR resourceName)&#xD;
{&#xD;
	TCHAR  szFilePath[MAX_PATH + 1];&#xD;
	GetPath(szFilePath,resourceName);//.dotnet4.exe&#xD;
	int result = ::DeleteFile(szFilePath);&#xD;
	return result;&#xD;
}&lt;/pre&gt;&#xD;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;&#xD;
&lt;/fieldset&gt;&#xD;
&lt;p&gt;接着再次检查注册表项&lt;/p&gt;&#xD;
&lt;p&gt;result = CheckDotNet4();&lt;/p&gt;&#xD;
&lt;p&gt;如果仍旧没有相关的注册表项&lt;/p&gt;&#xD;
&lt;p&gt;那么说明预安装程序没有安装成功，退出程序&lt;/p&gt;&#xD;
&lt;p&gt;---------------------&lt;/p&gt;&#xD;
&lt;p&gt;至此，检查工作已经完成&lt;/p&gt;&#xD;
&lt;p&gt;入口函数里剩下的代码&lt;/p&gt;&#xD;
&lt;p&gt;是执行目标程序的工作&lt;/p&gt;&#xD;
&lt;p&gt;不在多做解释&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b;"&gt;&#xD;
&lt;pre&gt;result = FreeRC(MAKEINTRESOURCE(1001),tarName);&#xD;
	if(result == 0)&#xD;
	{&#xD;
		Alert("没有成功释放应用程序~安装失败");&#xD;
		ClearFile(netName);&#xD;
		ClearFile(tarName);&#xD;
		return 0;&#xD;
	}&#xD;
	result = CreateInstallProcess(tarName);&#xD;
	if(result == 0)&#xD;
	{&#xD;
		Alert("没有成功启动应用程序进程~安装失败");&#xD;
	}&#xD;
	ClearFile(netName);&#xD;
	ClearFile(tarName);&lt;/pre&gt;&#xD;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;&#xD;
&lt;/fieldset&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;---------------------------&lt;/p&gt;&#xD;
&lt;p&gt;打包工具源码下载：&lt;a title="BagDotNet_code.zip" href="http://files.cnblogs.com/liulun/BagDotNet_code.zip"&gt;BagDotNet_code.zip&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;宿主程序源码下载：&lt;a title="CheckDotNet_code.zip" href="http://files.cnblogs.com/liulun/CheckDotNet_code.zip"&gt;CheckDotNet_code.zip&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;--------------------------------------------------------&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;span style="font-size: x-large;"&gt;如果您喜欢我的文章，请您推荐我的文章吧~谢谢~&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/liulun/aggbug/2298533.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/liulun/archive/2011/12/22/2298533.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/liulun/archive/2011/12/19/2292878.html</id><title type="text">DotNet4应用程序打包工具-&amp;gt;升级版【二】安装工具分析</title><summary type="text">在本系列的上一篇中，我们给出了这个工具的具体的思路。得到了很多朋友的反馈！综合朋友的意见，在没有改变工具原理的基础上我对这个程序做了升级如下图：如你所见，现在这个打包工具可以打包dotNet2.0 3.5 4乃至所有在注册表中添加过注册表项的应用程序下面我们就开始分析安装工具（也就是上面你看到的那个图片）--------------------------入口函数：int WinMain(HINSTANCE hInstance,HINSTANCE hPreInstance,LPSTR lpCmdLine,int nCmdShow){ DialogBox(hInstance,MAKEINTRE.</summary><published>2011-12-18T23:23:00Z</published><updated>2011-12-18T23:23:00Z</updated><author><name>liulun</name><uri>http://www.cnblogs.com/liulun/</uri></author><link rel="alternate" href="http://www.cnblogs.com/liulun/archive/2011/12/19/2292878.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/liulun/archive/2011/12/19/2292878.html"/><content type="html">&lt;p&gt;在本系列的&lt;a href="http://www.cnblogs.com/liulun/archive/2011/12/12/2284360.html"&gt;上一篇&lt;/a&gt;中，&lt;/p&gt;&#xD;
&lt;p&gt;我们给出了这个工具的具体的思路。&lt;/p&gt;&#xD;
&lt;p&gt;得到了很多朋友的反馈！&lt;/p&gt;&#xD;
&lt;p&gt;综合朋友的意见，&lt;/p&gt;&#xD;
&lt;p&gt;在没有改变工具原理的基础上&lt;/p&gt;&#xD;
&lt;p&gt;我对这个程序做了升级&lt;/p&gt;&#xD;
&lt;p&gt;如下图：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/liulun/201112/201112190721508504.png"&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;" title="image" src="http://images.cnblogs.com/cnblogs_com/liulun/201112/201112190721515572.png" alt="image" width="504" height="248" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;如你所见，&lt;/p&gt;&#xD;
&lt;p&gt;现在这个打包工具可以打包dotNet2.0&amp;nbsp; 3.5&amp;nbsp; 4&lt;/p&gt;&#xD;
&lt;p&gt;乃至所有在注册表中添加过注册表项的应用程序&lt;/p&gt;&#xD;
&lt;p&gt;下面我们就开始分析安装工具（也就是上面你看到的那个图片）&lt;/p&gt;&#xD;
&lt;p&gt;--------------------------&lt;/p&gt;&#xD;
&lt;p&gt;入口函数：&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b;"&gt;&#xD;
&lt;pre&gt;int WinMain(HINSTANCE hInstance,HINSTANCE hPreInstance,LPSTR lpCmdLine,int nCmdShow)&#xD;
{	&#xD;
	DialogBox(hInstance,MAKEINTRESOURCE(MainWinDL),0,DlgProc);&#xD;
	return 0;&#xD;
}&lt;/pre&gt;&#xD;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;&#xD;
&lt;/fieldset&gt;&#xD;
&lt;p&gt;好吧，入口函数很简单，只是创建了一个窗体，并注册了窗口过程函数&lt;/p&gt;&#xD;
&lt;p&gt;-----------------------------&lt;/p&gt;&#xD;
&lt;p&gt;窗口过程&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b;"&gt;&#xD;
&lt;pre&gt;//窗口过程&#xD;
BOOL CALLBACK DlgProc (HWND hDlg, UINT message,WPARAM wParam, LPARAM lParam)&#xD;
{&#xD;
    switch (message)&#xD;
    {&#xD;
		case WM_INITDIALOG :&#xD;
			OnInitDlg(hDlg);&#xD;
			return TRUE ;&#xD;
		case WM_COMMAND :&#xD;
			switch (LOWORD(wParam))&#xD;
			{&#xD;
				case IDC_STATIC_Name:&#xD;
					ShellExecute(hDlg,"open","http://www.cnblogs.com/liulun",NULL,NULL,SW_SHOWNORMAL); &#xD;
					break;&#xD;
				case IDC_BUTTON1:	&#xD;
					GetFile(hDlg,IDC_EDIT1);&#xD;
					break;&#xD;
				case IDC_BUTTON3:&#xD;
					GetFile(hDlg,IDC_EDIT3);&#xD;
					break;&#xD;
				case IDC_RADIO1:&#xD;
					CheckRadio(hDlg,IDC_RADIO1,"SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v2.0.50727");&#xD;
					break;&#xD;
				case IDC_RADIO2:&#xD;
					CheckRadio(hDlg,IDC_RADIO2,"SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v3.5");&#xD;
					break;&#xD;
				case IDC_RADIO3:&#xD;
					CheckRadio(hDlg,IDC_RADIO3,"SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v4");&#xD;
					break;&#xD;
				case IDC_RADIO_ELSE:&#xD;
					CheckRadio(hDlg,IDC_RADIO_ELSE,"");&#xD;
					break;&#xD;
				case IDOK:&#xD;
					ReleaseTar(hDlg);&#xD;
					ReplaceICO(hDlg);&#xD;
					BagTar(hDlg,IDC_EDIT3);&#xD;
					BagTar(hDlg,IDC_EDIT1);&#xD;
					BagStr(hDlg);&#xD;
					Alert("打包成功");&#xD;
					break;&#xD;
				case IDCANCEL:&#xD;
					EndDialog (hDlg, 0) ;&#xD;
					return TRUE ;&#xD;
			}&#xD;
		break;&#xD;
    }&#xD;
    return FALSE ;&#xD;
}&lt;/pre&gt;&#xD;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;&#xD;
&lt;/fieldset&gt;&#xD;
&lt;p&gt;在这个过程函数里&lt;/p&gt;&#xD;
&lt;p&gt;接收到的每个消息都执行了一个或几个函数&lt;/p&gt;&#xD;
&lt;p&gt;那么，我们就一个函数一个函数的讲&lt;/p&gt;&#xD;
&lt;p&gt;-------------------------------------------------------&lt;/p&gt;&#xD;
&lt;p&gt;窗口初始化消息里&lt;/p&gt;&#xD;
&lt;p&gt;我们默认选中了dotNet4的单选按钮&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b;"&gt;&#xD;
&lt;pre&gt;void OnInitDlg(HWND hwnd)&#xD;
{&#xD;
	HWND cld = ::GetDlgItem(hwnd,IDC_RADIO3);&#xD;
	::SendMessage(cld,BM_SETCHECK,1,0);&#xD;
	::SetDlgItemText(hwnd,IDC_EDIT2,"SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v4");&#xD;
	LastCheckRdioId = IDC_RADIO3;&#xD;
}&lt;/pre&gt;&#xD;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;&#xD;
&lt;/fieldset&gt;&#xD;
&lt;p&gt;---------------------------------------------------------&lt;/p&gt;&#xD;
&lt;p&gt;四个单选按钮的单击事件&lt;/p&gt;&#xD;
&lt;p&gt;设置了文本框的内容，&lt;/p&gt;&#xD;
&lt;p&gt;并记录了当前选中的是哪个单选按钮&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b;"&gt;&#xD;
&lt;pre&gt;void CheckRadio(HWND hwnd,int rdioID,LPCSTR val)&#xD;
{&#xD;
	if(rdioID == LastCheckRdioId)&#xD;
	{&#xD;
		return;&#xD;
	}&#xD;
	::SetDlgItemText(hwnd,IDC_EDIT2,val);&#xD;
	LastCheckRdioId = rdioID;&#xD;
}&lt;/pre&gt;&#xD;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;&#xD;
&lt;/fieldset&gt;&#xD;
&lt;p&gt;------------------------------------------------------------&lt;/p&gt;&#xD;
&lt;p&gt;选择文件&lt;/p&gt;&#xD;
&lt;p&gt;把选中的文件路径赋值给相应的文本框&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b;"&gt;&#xD;
&lt;pre&gt;//得到文件&#xD;
void GetFile(HWND hwnd,int EDITId)&#xD;
{&#xD;
	char szFile[MAX_PATH] = {0};&#xD;
	OPENFILENAME ofn;&#xD;
	memset(&amp;amp;ofn, 0, sizeof(OPENFILENAME));   &#xD;
	ofn.lStructSize = sizeof(OPENFILENAME);     &#xD;
	ofn.lpstrFile = szFile;   &#xD;
	ofn.nMaxFile = MAX_PATH;   &#xD;
	ofn.lpstrFilter = "应用程序 (.exe)\0*.exe\0\0";&#xD;
	ofn.lpstrDefExt = "exe";   &#xD;
	ofn.lpstrTitle = "选择exe文件";&#xD;
	ofn.nFilterIndex = 1;   &#xD;
	ofn.lpstrFileTitle = NULL;   &#xD;
	ofn.nMaxFileTitle = 0;   &#xD;
	ofn.lpstrInitialDir = NULL;&#xD;
	if(GetOpenFileName(&amp;amp;ofn))&#xD;
	{&#xD;
		SetDlgItemText(hwnd,EDITId,szFile);&#xD;
	}&#xD;
}&lt;/pre&gt;&#xD;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;&#xD;
&lt;/fieldset&gt;&#xD;
&lt;p&gt;&lt;br /&gt;--------------------------------------------------------------------&lt;/p&gt;&#xD;
&lt;p&gt;从资源中读取宿主程序，并按指定的文件名，释放到当前目录下&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b;"&gt;&#xD;
&lt;pre&gt;//释放资源&#xD;
int ReleaseTar(HWND hwnd)&#xD;
{	&#xD;
	::GetDlgItemText(hwnd,IDC_EDIT1,szFilePath,MAX_PATH);&#xD;
	::strcat(szFilePath,".bag.exe");&#xD;
&#xD;
	HMODULE hInstance = ::GetModuleHandle(NULL);&#xD;
    HRSRC hResID = ::FindResource(hInstance,(LPCSTR)IDR_BIN1,"bin"); &#xD;
    HGLOBAL hRes = ::LoadResource(hInstance,hResID);&#xD;
    LPVOID pRes = ::LockResource(hRes);&#xD;
    DWORD dwResSize = ::SizeofResource(hInstance,hResID);&#xD;
	if(!dwResSize)&#xD;
	{&#xD;
		return 0;&#xD;
	}&#xD;
    HANDLE hResFile = CreateFile(szFilePath,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);    &#xD;
    DWORD dwWritten = 0;&#xD;
    WriteFile(hResFile,pRes,dwResSize,&amp;amp;dwWritten,NULL);&#xD;
    CloseHandle(hResFile);&#xD;
    if(dwResSize == dwWritten);&#xD;
	{&#xD;
		return 1;&#xD;
	}&#xD;
	return 0;&#xD;
}&lt;/pre&gt;&#xD;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;&#xD;
&lt;/fieldset&gt;&#xD;
&lt;p&gt;---------------------------------------------------------------------------&lt;/p&gt;&#xD;
&lt;p&gt;替换宿主程序的ICO图标资源&lt;/p&gt;&#xD;
&lt;p&gt;这里需要重点说明一下：&lt;/p&gt;&#xD;
&lt;p&gt;要想更新一个应用程序的资源&lt;/p&gt;&#xD;
&lt;p&gt;必须先知道这个资源的ID&lt;/p&gt;&#xD;
&lt;p&gt;GetIcoIndex函数的工作就是获取资源ID的&lt;/p&gt;&#xD;
&lt;p&gt;因为一般的应用程序图标资源都会有两个&lt;/p&gt;&#xD;
&lt;p&gt;所以获取了两个图表资源的ID&lt;/p&gt;&#xD;
&lt;p&gt;其他的WINAPI就不多解释了~~&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b;"&gt;&#xD;
&lt;pre&gt;int GetIcoIndex(HMODULE hExe,int index[])&#xD;
{&#xD;
	HRSRC hRes;&#xD;
	int iLoop;&#xD;
	int i = 0;&#xD;
	for(iLoop = 1;;iLoop++)&#xD;
    {&#xD;
        hRes = FindResource(hExe, MAKEINTRESOURCE(iLoop), RT_ICON); &#xD;
		if (NULL == hRes)&#xD;
		{&#xD;
			if(iLoop == 60)&#xD;
			{&#xD;
				break;&#xD;
			}&#xD;
			continue ; &#xD;
		}&#xD;
        else&#xD;
		{&#xD;
			index[i]  = iLoop;&#xD;
			i +=1;&#xD;
			if(i == 2)&#xD;
			{&#xD;
				break;&#xD;
			}&#xD;
		}&#xD;
    }&#xD;
	return 1;&#xD;
}&#xD;
int ReplaceICO(HWND hwnd)&#xD;
{&#xD;
	HMODULE hSrcExe,hDestExe;&#xD;
	HANDLE hUpdateRes;&#xD;
	HRSRC hRes;&#xD;
	HRSRC hResLoad;&#xD;
	char *lpResLock;&#xD;
	int result;&#xD;
	char szFile[MAX_PATH+1] = {0};&#xD;
	int hSrcIndex[2] = {0};&#xD;
	int hDestIndex[2] = {0};&#xD;
	::GetDlgItemText(hwnd,IDC_EDIT1,szFile,MAX_PATH);&#xD;
	hSrcExe = LoadLibrary(szFile);&#xD;
	hDestExe = LoadLibrary(szFilePath);&#xD;
	GetIcoIndex(hSrcExe,hSrcIndex);&#xD;
	GetIcoIndex(hDestExe,hDestIndex);&#xD;
	for(int i=0;i&amp;lt;2;i++)&#xD;
	{&#xD;
		hRes = FindResource(hSrcExe, MAKEINTRESOURCE(hSrcIndex[i]), RT_ICON); &#xD;
		hResLoad=(HRSRC)LoadResource(hSrcExe,hRes);&#xD;
		lpResLock=(char*)LockResource(hResLoad);&#xD;
		FreeLibrary(hDestExe);&#xD;
		hUpdateRes=BeginUpdateResource(szFilePath,FALSE);&#xD;
		result=UpdateResource(hUpdateRes,RT_ICON,MAKEINTRESOURCE(hDestIndex[i]),MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),lpResLock,SizeofResource(hSrcExe,hRes));&#xD;
		EndUpdateResource(hUpdateRes, FALSE);&#xD;
	}&#xD;
	FreeLibrary(hSrcExe);&#xD;
	return result;&#xD;
}&lt;/pre&gt;&#xD;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;&#xD;
&lt;/fieldset&gt;&#xD;
&lt;p&gt;---------------------------------------&lt;/p&gt;&#xD;
&lt;p&gt;为宿主程序增加目标程序资源和dotNet安装包资源&lt;/p&gt;&#xD;
&lt;p&gt;增加的资源也是需要标明ID的&lt;/p&gt;&#xD;
&lt;p&gt;因为宿主程序会根据约定好的ID来得到这些资源&lt;/p&gt;&#xD;
&lt;p&gt;EditId参数就是这些资源的ID&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b;"&gt;&#xD;
&lt;pre&gt;int BagTar(HWND hwnd,int EditId)&#xD;
{&#xD;
	HANDLE hFile;&#xD;
	DWORD dwFileSize,dwBytesRead;&#xD;
	LPBYTE lpBuffer;&#xD;
	char szFile[MAX_PATH+1] = {0};&#xD;
	::GetDlgItemText(hwnd,EditId,szFile,MAX_PATH);&#xD;
	hFile = CreateFile(szFile,GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);&#xD;
	dwFileSize = GetFileSize(hFile, NULL);&#xD;
	lpBuffer = new BYTE[dwFileSize];&#xD;
	ReadFile(hFile, lpBuffer, dwFileSize, &amp;amp;dwBytesRead, NULL);&#xD;
	HANDLE hResource = BeginUpdateResource(szFilePath, FALSE);&#xD;
	UpdateResource(hResource,RT_RCDATA,MAKEINTRESOURCE(EditId),MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),(LPVOID)lpBuffer,dwFileSize);	&#xD;
	EndUpdateResource(hResource, FALSE);	&#xD;
	delete [] lpBuffer; &#xD;
	CloseHandle(hFile);&#xD;
	return 1;&#xD;
}&lt;/pre&gt;&#xD;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;&#xD;
&lt;/fieldset&gt;&#xD;
&lt;p&gt;--------------------------------------------------------&lt;/p&gt;&#xD;
&lt;p&gt;把注册表项的路径也当作资源打包进宿主程序&lt;/p&gt;&#xD;
&lt;p&gt;我们约定这个资源的ID为1039&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b;"&gt;&#xD;
&lt;pre&gt;int BagStr(HWND hwnd)&#xD;
{&#xD;
	char szFile[MAX_PATH+1] = {0};&#xD;
	::GetDlgItemText(hwnd,IDC_EDIT2,szFile,MAX_PATH);&#xD;
	HANDLE hUpdateRes=BeginUpdateResource(szFilePath,FALSE);&#xD;
	int result=UpdateResource(hUpdateRes,RT_RCDATA,MAKEINTRESOURCE(1039),MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),(LPVOID)szFile,::strlen(szFile));&#xD;
	EndUpdateResource(hUpdateRes, FALSE);&#xD;
	return 0;&#xD;
}&lt;/pre&gt;&#xD;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;&#xD;
&lt;/fieldset&gt;&#xD;
&lt;p&gt;-------------------------------------------------------------&lt;/p&gt;&#xD;
&lt;p&gt;其他的一些代码如下&lt;/p&gt;&#xD;
&lt;fieldset style="background-color: #e0eff6; width: 900px; color: #15428b;"&gt;&#xD;
&lt;pre&gt;#include &amp;lt;Windows.h&amp;gt;&#xD;
#include &amp;lt;ShlObj.h&amp;gt;&#xD;
#include "resource.h"&#xD;
&#xD;
TCHAR szFilePath[MAX_PATH + 1];&#xD;
&#xD;
int LastCheckRdioId;&#xD;
//提示&#xD;
void Alert(LPCSTR msg)&#xD;
{&#xD;
	MessageBox(NULL,msg,"系统提示",MB_OK);	&#xD;
}&lt;/pre&gt;&#xD;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;&#xD;
&lt;/fieldset&gt;&#xD;
&lt;p&gt;---------------------------------------------------------------&lt;/p&gt;&#xD;
&lt;p&gt;后记：&lt;/p&gt;&#xD;
&lt;p&gt;没有写容错的代码~&lt;/p&gt;&#xD;
&lt;p&gt;也没有遵循命名规范~&lt;/p&gt;&#xD;
&lt;p&gt;大家见谅~&lt;/p&gt;&#xD;
&lt;p&gt;请各位推荐我的文章&lt;/p&gt;&#xD;
&lt;p&gt;因为你们的支持才是我的动力-&amp;gt;-&amp;gt;-&amp;gt;-&amp;gt;-&amp;gt;-&amp;gt;-&amp;gt;-&amp;gt;-&amp;gt;-&amp;gt;-&amp;gt;-&amp;gt;-&amp;gt;-&amp;gt;-&amp;gt;-&amp;gt;-&amp;gt;-&amp;gt;-&amp;gt;-&amp;gt;-&amp;gt;-&amp;gt;-&amp;gt;-&amp;gt;-&amp;gt;-&amp;gt;-&amp;gt;-&amp;gt;-&amp;gt;-&amp;gt;-&amp;gt;-&amp;gt;-&amp;gt;-&amp;gt;-&amp;gt;-&amp;gt;-&amp;gt;-&amp;gt;-&amp;gt;-&amp;gt;-&amp;gt;-&amp;gt;-&amp;gt;-&amp;gt;-&amp;gt;-&amp;gt;-&amp;gt;-&amp;gt;&lt;/p&gt;&#xD;
&lt;p&gt;此工具编译后的可执行文件下载地址：&lt;a title="BagDotNet.zip" href="http://files.cnblogs.com/liulun/BagDotNet.zip"&gt;BagDotNet.zip&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;（因为不在需要把dotNet4安装程序打包进来，所以只有几十K了！多轻便啊！）&lt;/p&gt;&lt;img src="http://www.cnblogs.com/liulun/aggbug/2292878.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/liulun/archive/2011/12/19/2292878.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
