“托管扩展性框架(Managed Extensibility Framework,简称MEF),是微软.NET框架下为提高应用和组件复用程度而推出的,用于使组件能够最大化的重用。使用MEF能够使静态编译的.NET应用程序转换为动态组合,这将是创建可扩展应用、可扩展框架和应用扩展的好途径。它将做为.NET Framework 4.0的组成部分之一发布。现在,MEF也将被包含在Silverlight 4.0中。
那么MEF是怎样工作的呢?简单分为三个步骤:
•Export (输出)
•Import (输入)
•Compose (组合)
简短说一下MEF的工作原理,MEF的核心包括一个catalog和一个CompositionContainer。category用于发现扩展,而container用于协调创建和梳理依赖性。每个可组合的Part提供了一个或多个Export,并且通常依赖于一个或多个外部提供的服务或Import。每个Part管理一个实例为应用程序运行。
下面我们做一个小型可扩展计算器示例来解释这三个过程
1.首先下载MEF框架包,Silverlight 4.0会自带,不过微软已经将其开源了。
http://www.codeplex.com/MEF
2.创建一个Silverlight Navigate Application ,并添加程序集引用(MEF_Beta_2\bin\SL目录下 System.ComponentModel.Composition.dll)
在项目下添加两个类文件Package.cs和PackageCatalog.cs,这两个文件在最新的MEF版本中没有提供,主要用于加载silverlight的Xap包。
这两个文件在MEF框架的Sample中提供了(MEF_Beta_2\Samples\PictureViewer\PictureViewer.Common),将这两个类的访问修饰符改为public, 添加后注意修改命名空间。
3.修改Home.cs 类
代码
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ComponentModel.Composition;
using System.ComponentModel;
namespace MefDemo
{
//用于更新界面的委托
public delegate void OperateHandler(IOperate Op);
/// <summary>
/// 运算器接口
/// </summary>
public interface IOperate
{
double Op(double left, double right);
string Symbol { set; get; }
string Label { get; set; }
}
/// <summary>
/// 加法运算器
/// </summary>
[Export(typeof(IOperate))]
public class AddButton : Button, IOperate
{
[Import("AddButtonContract",AllowRecomposition = true)]
public string Label { get { return this.Content.ToString(); } set { this.Content = value; } }
[Import("AddSybomContract", AllowRecomposition = true)]
public string Symbol { set; get; }
[Import("ClickHandler")]
public OperateHandler ClickAction { get; set; }
#region IOperate 成员
public double Op(double left, double right)
{
return left + right;
}
#endregion
public AddButton()
{
this.Click += (s, e) => ClickAction(this);
}
}
/// <summary>
/// 减法运算器
/// </summary>
[Export(typeof(IOperate))]
public class SubButton : Button, IOperate
{
[Import("SubButtonContract",AllowRecomposition=true)]
public string Label { get { return this.Content.ToString(); } set { this.Content = value; } }
[Import("SubSybomContract", AllowRecomposition = true)]
public string Symbol { set; get; }
[Import("ClickHandler")]
public OperateHandler ClickAction { get; set; }
#region IOperate 成员
public double Op(double left, double right)
{
return left - right;
}
#endregion
public SubButton()
{
this.Click += (s, e) => ClickAction(this);
}
}
/// <summary>
/// 为每个运算器的属性提供值
/// </summary>
public class ComponentAttributeProvider
{
[Export("AddButtonContract")]
public string AddLabel { get { return "Add"; } }
[Export("AddSybomContract")]
public string AddSymbol { get { return "+"; } }
[Export("SubButtonContract")]
public string SubLabel { get { return "Sub"; } }
[Export("SubSybomContract")]
public string SubSymbol { get { return "-"; } }
}
}
4.修改 Home.xaml
代码
<navigation:Page x:Class="MefDemo.Home"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480"
Title="Home"
Style="{StaticResource PageStyle}">
<navigation:Page.Resources>
<ItemsPanelTemplate x:Key="ItemsPanelTemplate1">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</ItemsPanelTemplate>
</navigation:Page.Resources>
<Grid x:Name="LayoutRoot">
<ScrollViewer x:Name="PageScrollViewer" Style="{StaticResource PageScrollViewerStyle}">
<StackPanel x:Name="ContentStackPanel" Background="Black">
<StackPanel Orientation="Horizontal" Width="455" Height="89" Margin="91,0,91,-30">
<TextBox x:Name="LeftNum" HorizontalAlignment="Left" VerticalAlignment="Center" Width="83" TextWrapping="Wrap"/>
<TextBlock x:Name="Symbol" Width="62" Text="+" TextWrapping="Wrap" FontSize="24" Foreground="#FFF80606" TextAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Left"/>
<TextBox x:Name="RightNum" HorizontalAlignment="Left" VerticalAlignment="Center" Width="78" TextWrapping="Wrap"/>
<TextBlock Width="64" Text="=" TextWrapping="Wrap" Foreground="#FFF20808" FontSize="21.333" TextAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Left"/>
<TextBox x:Name="Result" HorizontalAlignment="Left" VerticalAlignment="Center" Width="146" TextWrapping="Wrap"/>
</StackPanel>
<ListBox x:Name="operateList" ItemsSource="{Binding}" ItemsPanel="{StaticResource ItemsPanelTemplate1}" Height="99" Background="{x:Null}" BorderBrush="{x:Null}"/>
<Button x:Name="DynamicLoadButton" Height="40" Width="196" Content="DynamicLoadOperate"/>
</StackPanel>
</ScrollViewer>
</Grid>
</navigation:Page>
5.新建类 OperatorComponent.cs
代码
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ComponentModel.Composition;
using System.ComponentModel;
namespace MefDemo
{
//用于更新界面的委托
public delegate void OperateHandler(IOperate Op);
/// <summary>
/// 运算器接口
/// </summary>
public interface IOperate
{
double Op(double left, double right);
string Symbol { set; get; }
string Label { get; set; }
}
/// <summary>
/// 加法运算器
/// </summary>
[Export(typeof(IOperate))]
public class AddButton : Button, IOperate
{
[Import("AddButtonContract",AllowRecomposition = true)]
public string Label { get { return this.Content.ToString(); } set { this.Content = value; } }
[Import("AddSybomContract", AllowRecomposition = true)]
public string Symbol { set; get; }
[Import("ClickHandler")]
public OperateHandler ClickAction { get; set; }
#region IOperate 成员
public double Op(double left, double right)
{
return left + right;
}
#endregion
public AddButton()
{
this.Click += (s, e) => ClickAction(this);
}
}
/// <summary>
/// 减法运算器
/// </summary>
[Export(typeof(IOperate))]
public class SubButton : Button, IOperate
{
[Import("SubButtonContract",AllowRecomposition=true)]
public string Label { get { return this.Content.ToString(); } set { this.Content = value; } }
[Import("SubSybomContract", AllowRecomposition = true)]
public string Symbol { set; get; }
[Import("ClickHandler")]
public OperateHandler ClickAction { get; set; }
#region IOperate 成员
public double Op(double left, double right)
{
return left - right;
}
#endregion
public SubButton()
{
this.Click += (s, e) => ClickAction(this);
}
}
/// <summary>
/// 为每个运算器的属性提供值
/// </summary>
public class ComponentAttributeProvider
{
[Export("AddButtonContract")]
public string AddLabel { get { return "Add"; } }
[Export("AddSybomContract")]
public string AddSymbol { get { return "+"; } }
[Export("SubButtonContract")]
public string SubLabel { get { return "Sub"; } }
[Export("SubSybomContract")]
public string SubSymbol { get { return "-"; } }
}
}
6.运行。 这样就构建了一个简单的运算器,其中的Export、Import就像一个个管道一样相互连接。
7.按照这样的设计,我们想要对其进行扩展,就必须把接口分离。新建一个Silverlight ClassLibrary Project(Named ContractLibrary),这个Library用来封装所有的扩展接口,定义Import/Export契约。
现在把原项目中的OperatorComponent.cs 类中的接口迁移到Library项目中,新建类文件OperateContract.cs 。
代码
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace ContractLibrary
{
public delegate void OperateHandler(IOperate Op);
/// <summary>
/// 运算器接口
/// </summary>
public interface IOperate
{
double Op(double left, double right);
string Symbol { set; get; }
string Label { get; set; }
}
}
编译通过后在Silverlight主工程(MefDemo)中添加对ContractLibrary项目的引用
8.再新建一个Silverlight ClassLibrary Project (Named StaticExtension),,这个工程就是我们用来静态扩展的DLL。
a). 在工程下新建我们的运算器类,AddButton.cs , SubButton.cs.(代码不变).
b). 但注意要添加对ContractLibrary项目的引用和MEF的框架集引用) 。
c). 添加全局属性配置类(ComponentConfiguration.cs)
d). 删除主工程中的ComponetOperater.cs.
e). 添加对StaticExtension的引用.
9.OK,这样我们就可以任意扩展运算器,添加更多的扩展运算了。
10.那么下面是添加一个新的乘法运算所要做的工作。
在StaticExtension中添加新类 Multiply.cs
代码
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ComponentModel.Composition;
using ContractLibrary;
namespace StaticExtension
{
/// <summary>
/// 乘法运算器
/// </summary>
[Export(typeof(IOperate))]
public class MultiplyButton : Button, IOperate
{
[Import("MultiplyButtonContract", AllowRecomposition = true)]
public string Label { get { return this.Content.ToString(); } set { this.Content = value; } }
[Import("MultiplySybomContract", AllowRecomposition = true)]
public string Symbol { set; get; }
[Import("ClickHandler")]
public OperateHandler ClickAction { get; set; }
#region IOperate 成员
public double Op(double left, double right)
{
return left * right;
}
#endregion
public MultiplyButton()
{
this.Click += (s, e) => ClickAction(this);
}
}
}
11.上面的是静态加载,那么现在我们使用MEF实现动态扩展运算器。桌面程序的动态扩展是动态加载DLL,而对于Silverlight的Web程序则是动态加载Xap包了。
新建普通Silverlight Application(Named DynamicExtension).
去掉勾选Add a test page that references the application.
1). 删掉App和Main等不必要的文件,只留一个空的Silverlight项目,以减少Xap包的大小。
2). 添加ContractLibrary和MEF框架集的引用(可以将引用程序集属性CopyLocal设置为false,因为我们在主工程中已经添加了,可以重用)
3). 添加类Division.cs.
代码
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ComponentModel.Composition;
using ContractLibrary;
namespace DynamicExtension
{
/// <summary>
/// 乘法运算器
/// </summary>
[Export(typeof(IOperate))]
public class DivisionButton : Button, IOperate
{
[Import("DivisionButtonContract", AllowRecomposition = true)]
public string Label { get { return this.Content.ToString(); } set { this.Content = value; } }
[Import("DivisionSybomContract", AllowRecomposition = true)]
public string Symbol { set; get; }
[Import("ClickHandler")]
public OperateHandler ClickAction { get; set; }
#region IOperate 成员
public double Op(double left, double right)
{
return left * right;
}
#endregion
public DivisionButton()
{
this.Click += (s, e) => ClickAction(this);
}
}
}
4). 添加配置类ComponentConfiguration.cs
代码
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ComponentModel.Composition;
namespace DynamicExtension
{
/// <summary>
/// 为每个运算器的属性配置值
/// </summary>
public class ComponentConfiguration
{
[Export("DivisionButtonContract")]
public string AddLabel { get { return "Div"; } }
[Export("DivisionSybomContract")]
public string AddSymbol { get { return "/"; } }
}
}
5). 修改Home.cs ,为其注册下载包的相关事件和回调
1.
代码
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using System.Collections.ObjectModel;
using System.ComponentModel.Composition.Hosting;
using System.Reflection;
using System.ComponentModel.Composition;
using ContractLibrary;
namespace MefDemo
{
public partial class Home : Page
{
[ImportMany(typeof(IOperate),AllowRecomposition = true)]
public ObservableCollection<IOperate> Operates = new ObservableCollection<IOperate>();
[Export("ClickHandler")]
public OperateHandler ClickHandler { get { return OperateButton_Click; } }
private PackageCatalog Catalog;
/// <summary>
/// 用于界面控件响应运算后的一些更新工作
/// </summary>
/// <param name="Operate">运算器</param>
public void OperateButton_Click(IOperate Operate)
{
try
{
Symbol.Text = Operate.Symbol;
double left = double.Parse(LeftNum.Text);
double right = double.Parse(RightNum.Text);
this.Result.Text = Operate.Op(left, right).ToString();
}
catch (Exception e)
{
ChildWindow errorWin = new ErrorWindow(e);
errorWin.Show();
}
}
public Home()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(Home_Loaded);
//注册按钮事件
this.DynamicLoadButton.Click += (s, e) =>
{
//下载包
Package.DownloadPackageAsync(
new Uri("DynamicExtension.xap", UriKind.Relative),
(args, package) => Catalog.AddPackage(package)
);
//包被添加到PackageCatalog后会自动重新组合
//并对添加了AllowRecomposition = true属性的Import导入器重新输入数据
};
}
void Home_Loaded(object sender, RoutedEventArgs e)
{
//组合当前XAP包中所有部件(Parts)
Catalog = new PackageCatalog();
Catalog.AddPackage(Package.Current);
CompositionContainer container = new CompositionContainer(Catalog);
container.ComposeParts(this);
//组合后所有实现运算接口(IOperate)的运算器都将被自动填充到 Operates 集合。
//将运算器绑定到 ListBox 控件,用于呈现。
this.operateList.DataContext = Operates;
}
// Executes when the user navigates to this page.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
}
}
}
Ok,最终界面。
点击DynamicLoadOperate按钮后
程序中还有很多细节没有展开说明,理论性的介绍可以参考MSDN和CodePlex上的文档。
文章出处:飞诺网(www.firnow.com):http://dev.firnow.com/course/4_webprogram/asp.net/netjs/20100714/442928.html
MEF gives us the ability to do this. This post will cover the basics needed to build such a composite application split between different silerlight applications and download the referenced silverlight application only when needed.
Steps:
- Create a Silverlight 4 application
- Add references to the following assemblies:
System.ComponentModel.Composition.dll
System.ComponentModel.Composition.Initialization.dll
- Add a new Silverlight 4 application called ExternalSilverlightApplication to the solution that was created in step 1. Ensure the new application is hosted in the web application for the solution and choose to not create a test page for the new application.
- Delete the App.xaml and MainPage.xaml files – they aren’t needed.
- Add references to the following assemblies in the ExternalSilverlightApplication project:
System.ComponentModel.Composition.dll
System.ComponentModel.Composition.Initialization.dll
- Ensure the two references above have their Copy Local values set to false. As we will have these two assmblies in the original Silverlight application, we will have no need to include them in the built ExternalSilverlightApplication build.
- Add a new user control called LeftControl to the ExternalSilverlightApplication project.
- Replace the LayoutRoot Grid with the following xaml:
<Grid x:Name="LayoutRoot" Background="Beige" Margin="40" >
<Button Content="Left Content" Margin="30"></Button>
</Grid>
- Add the following statement to the top of the LeftControl.xaml.cs file
using System.ComponentModel.Composition;
- Add the following attribute to the LeftControl class
[Export(typeof(LeftControl))]
This attribute tells MEF that the type LeftControl will be exported – i.e. made available for other applications to import and compose into the application.
- Add a new user control called RightControl to the ExternalSilverlightApplication project.
- Replace the LayoutRoot Grid with the following xaml:
<Grid x:Name="LayoutRoot" Background="Green" Margin="40" >
<TextBlock Margin="40" Foreground="White" Text="Right Control" FontSize="16" VerticalAlignment="Center" HorizontalAlignment="Center" ></TextBlock>
</Grid>
- Add the following statement to the top of the RightControl.xaml.cs file
using System.ComponentModel.Composition;
- Add the following attribute to the RightControl class
[Export(typeof(RightControl))]
- In your original Silverlight project add a reference to the ExternalSilverlightApplication project.
- Change the reference to the ExternalSilverlightApplication project to have it’s Copy Local value = false. This will ensure that the referenced ExternalSilverlightApplication Silverlight application is not included in the original Silverlight application package when it it built. The ExternalSilverlightApplication Silverlight application therefore has to be downloaded on demand by the original Silverlight application for it’s controls to be used.
- In your original Silverlight project add the following xaml to the LayoutRoot Grid in MainPage.xaml:
<Grid.RowDefinitions>
<RowDefinition Height="65*" />
<RowDefinition Height="235*" />
</Grid.RowDefinitions>
<Button Name="LoaderButton" Content="Download External Controls" Click="Button_Click"></Button>
<StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Center" >
<Border Name="LeftContent" Background="Red" BorderBrush="Gray" CornerRadius="20"></Border>
<Border Name="RightContent" Background="Red" BorderBrush="Gray" CornerRadius="20"></Border>
</StackPanel>
The borders will hold the controls that will be downlaoded, imported and composed via MEF when the button is clicked.
- Add the following statement to the top of the MainPage.xaml.cs file
using System.ComponentModel.Composition;
- Add the following properties to the MainPage class:
[Import(typeof(LeftControl))]
public LeftControl LeftUserControl { get; set; }
[Import(typeof(RightControl))]
public RightControl RightUserControl { get; set; }
This defines properties accepting LeftControl and RightControl types. The attrributes are used to tell MEF the discovered type that should be applied to the property when composition occurs.
- Add the following event handler for the button click to the MainPage.xaml.cs file:
private void Button_Click(object sender, RoutedEventArgs e)
{
DeploymentCatalog deploymentCatalog =
new DeploymentCatalog("ExternalSilverlightApplication.xap");
CompositionHost.Initialize(deploymentCatalog);
deploymentCatalog.DownloadCompleted += (s, i) =>
{
if (i.Error == null)
{
CompositionInitializer.SatisfyImports(this);
LeftContent.Child = LeftUserControl;
RightContent.Child = RightUserControl;
LoaderButton.IsEnabled = false;
}
};
deploymentCatalog.DownloadAsync();
}
This is where the magic happens! The deploymentCatalog object is pointed to the ExternalSilverlightApplication.xap file. It is then associated with the CompositionHost initialization. As the download will be asynchronous, an eventhandler is created for the DownloadCompleted event. The deploymentCatalog object is then told to start the asynchronous download.
The event handler that executes when the download is completed uses the CompositionInitializer.SatisfyImports() function to tell MEF to satisfy the Imports for the current class. It is at this point that the LeftUserControl and RightUserControl properties are initialized with composed objects from the downloaded ExternalSilverlightApplication.xap package.
- Run the application click the Download External Controls button and see the controls defined in the ExternalSilverlightApplication application loaded into the original Silverlight application.
Congratulations! You have implemented download on demand capabilities for composite applications using the MEF DeploymentCatalog class. You are now able to segment your applications into separate xap file for deployment.
.NET 4.0中提供了一个MEF框架用于开发支持插件的软件系统,幸运的是,Silverlight 4也支持MEF。这就使得我们可以很容易地实现以下的功能:
用户在访问Silverlight应用程序时,开始可以只显示一个“初始的简单的”页面,当用户需要时,动态从Web网站上下载新的程序集,然后,Silverlight客户端应用程序再使用MEF将动态下载的程序集中所包容的页面组件“组装”为一个新的功能增强了的页面。
示例解决方案DynamicComposePage展示了相关的技术细节。下面简要介绍一下其开发步骤。
1 使用Visual Studio 2010创建一个名为DynamicComposePage的 Silverlight Business Application项目。
Visual Studio 2010将会帮助我们创建一个名为DynamicComposePage.Web的ASP.NET网站,它引用名为DynamicComposePage的Silverlight项目。
在解决方案资源管理器中展开DynamicComposePage项目节点,在其Views文件夹下可以看到Visual Studio 2010生成的一个Home.xaml页面,等一会我们将修改此页面实现页面的动态装配。
2 现在需要提供一个MEF部件都遵循的接口,为此,向解决方案中添加一个“Silverlight类库(Silverlight Class Library)” 项目[1]MyPartContract,并向其中添加一个IMyPart接口,为简单起见,本例不为此接口添加任何成员,当然,在实际开发中可以依据需要为其添加合适的成员。
- namespace MyPartContract
- {
- public interface IMyPart
- {
- }
- }
[1] 注意:这不是普通的“类库”项目,Silverlight所使用的程序集是重新编写的,与标准的.NET Framework不一样。
3 下面定义可供动态组合的Silverlight页面组件。
向示例解决方案中添加一个名为“MyPageParts”的“Silverlight类库(Silverlight Class Library)” 项目,注意在弹出的对话框中选择“Silverlight 4”。
然后,向MyPageParts项目中添加一个“Silverlight User Control”,取名“MyEditorControl”,在这个页面中我们将放置一个RichTextArea控件充当文字编辑器:
- <UserControl x:Class="MyPageParts.MyEditor" ……>
- <RichTextArea x:Name="MyEditorControl" …… />
- </UserControl>
现在,需要让此用户控件可以被MEF动态装配,为此,需要完成两个步骤:
(1)给本项目(也包括前面创建的Silverlight项目DynamicComposePage)都添加对包容了IMyPart接口的Silverlight类库MyPartContract的引用。
(2)给本项目(也包括前面创建的Silverlight项目DynamicComposePage)都添加对MEF核心程序集System.ComponentModel.Composition.dll的引用,将要负责完成“装配”工作的Silverligh项目DynamicComposePage还需要添加对另一个核心程序集System.ComponentModel.Composition.Initialization.dll的引用。
附件: Snap8.jpg
注意:
在以下位置才能找到上述程序集:
C:\Program Files\Microsoft SDKs\Silverlight\v4.0\Libraries
下面是支持MEF动态装配的Silverlight 4用户控件的相应代码,注意其中的“[Export]”标记:
- [Export(typeof(IMyPart))]
- public partial class MyEditor : UserControl,IMyPart
- {
- public MyEditor()
- {
- InitializeComponent();
- }
- }
- 源码http://cid-887e6220d1fad37c.office.live.com/self.aspx/silverlight/DynamicComposePage.rar
正在编写中...
万事开头难。学什么东西一定要先入门,入了门你才能更深入学习。WCF已研究了一段时,总算有点眉目。在学习WCFf时,不管是书还是网上资料,都把WCF介绍的很复杂。但其实wcf并不想我想象的那样那么复杂。这里总结一下,并主要通过示例帮助他人快速入门。
WCF介绍
WCF是Windows Communication Foundation 的缩写,它是MS为SOA (Service Oriented Architecture)战略而设计的一套完整的技术框架。它是一种统一的编程模型,用来为微软平台编写分布式(Distributed)应用。涵盖了之前出现的多种技术,如ASMX,Remoting,MSMQ等等。
有哪些优点:
1.整合了多项技术,是MS SOA产品的集大成者。
2.更为简单易用。(它囊括了关于服务的一切,无论是服务的创建,托管,消费和安全保障,还是保护与互通,甚至是提高开发效率)
3.包含了 其他技术的所有优点(统一性,互操作性,可靠性,兼容性)
WCF与其它服务的比较,如下图。
WCF基础知识
在写WCF程序之前要对基本的理论知识进行了解。WCF程序的基本架构如下图:
WCF程序与Web Service程序类似,先编写服务器端,然后引用服务的方式进行开发。
服务
Wcf中的服务服务具有一个或多个终结点(endpoint)。终结点相当于端口,用于通信。
终结点主要由地址、绑定、契约三个部分组成。
地址(Address): 在哪里(也含有传输方式信息)
绑定(Binding) :怎么做(与地址的传输方式要匹配)
契约(Contract):做什么(服务契约)
服务宿主
服务宿主是服务建好后需要启动它,此启动的平台称为服务宿主。在宿主中,处理通信是由行为(behavior)的控制点(control point)决定。
客户端
只需要引用Wcf服务器并调用即可。
以上大体对WCF作了讲解。理论通过实践来学习,下边将会编写WCF的入门程序,通过程序来体会WCF。 当然如果想深入学习理论知识,可以找其它方面的资料来了解。
移除未使用的程序集
Visual Studio在创建sl应用后默认情况下加了很多的程序集,有些可能是你根本就用不上的。
首先除了System引用将所有其他的删除掉,然后重新编译应用,将缺失的DLL重新添加回来。有很多的错误可能是由于添加了命名空间的引用,这里有一个简单的来去掉未使用的命名空间(usings),右键点击一个类名,然后选择Organize usings / Remove unused usings。
重新打包XAP文件“越小越好”
我们知道Silverlight的XAP包实质上就是一个标准的ZIP包,包内有一个AppManifest使得他在Silverlgith运行时中可正确的被解析。但是Visual Studio 2008在做XAP打包时并没有做压缩。
这里我们要做的是Winzip活Winrar将这个XAP解包,然后再做压缩打包,将扩展名改成xap替换原始文件。
将素材放在sl应用外部
在之前方式中我们都是针对一个sl应用做的,但是当你在构建模块话的sl应用时,将素材文件放在Silverlight XAP包的外部效果会更好。(或者放在外部ZIP包中再做压缩,让sl应用动态获取。更多请看“Silverlight从Zip包中获取文件”未完成)
使用程序集缓存
使用程序集缓存的办法很简单只需要在sl的属性页面,将library Caching设置为true即可
动态加载XAP
在silverlight开发的过程中可以将模块话,分解成多个xap文件,有一个主xap来调用其他的xap做动态的加载.
举一个例子,让我们看看Photoshop这个网站,他是用flex技术完成的。
我们可以看出他的容器、类库以及样式都是动态的加载进去的。
在silverlight中可以用简单的loadingXAP来完成(具体请查看“动态加载XAP文件”),或者使用第三方的框架来完成,比如“Managed Extensibility Framework”、“Prism”。
这里我使用了Prism框架来开发我的一个项目,可以来看一下效果。
可以看出各个模块是逐个加载的。
- SilverLight Cache First Exploration
一、概述
用户打开同一SilverLight站点时,由于每次都要重新加载SilverLight应用程序包(.xap文件),因此会大大的降低用户体验。因此微软在SilverLight 3.0版本中提供了应用程序集缓存(Application Library Caching),可以解决这一缺陷。
应用程序集缓包括两个部分:
1、SilverLight本身的程序集缓存;
2、用户自定义程序集缓存。
下面分别介绍一下两种程序集缓存的实现方法:
二、SilverLight本身的程序集缓存
SilverLight在它的SDK中提供了很多程序集,这些程序集可以通过配置,当且仅当需要使用或者有更高版本时,才重新加载这些程序集,下面是配置步骤:
1、在应用"程序资源管理器"中选择需要配置的SilverLight项目;
2、点击右键,选择"属性";
3、在属性配置页中选择"SilverLight"卡,在SilverLight页面中选择"通过使用应用程序库缓存减小XAP大小"。
以上步骤就完成了相关配置,现在重新编译整个解决方案,编译成功后,可以在Web项目的ClientBin文件夹中,多了些项目中引用的SilverLight程序集的zip文件,另外xap文件的大小也减小了。
三、用户自定义程序集缓存
自定义程序集缓存所使用的程序集必须为强命名程序集(添加方法:略),下面是配置步骤:
1、在SilverLight项目的Bin/Debug目录下,找到要缓存的程序集;
2、在SilverLight项目的Bin/Debug添加对应程序集的映射文件,文件名为对应程序集的文件名,扩展为.extmap.xml(如:程序集名称为Microsoft.Windows.Controls.dll,对应映射为:Microsoft.Windows.Controls.extmap.xml);
3、用记事本打开映射文件,输入如下内容:
<?xml version="1.0"?>
<manifest xmlns:xsi=" http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd=" http://www.w3.org/2001/XMLSchema">
<assembly>
<name>Microsoft.Windows.Controls</name>
<version>2.0.21027.1502</version>
<publickeytoken>31bf3856ad364e35</publickeytoken>
<relpath>Microsoft.Windows.Controls.dll</relpath>
<extension downloadUri="Microsoft.Windows.Controls.zip" />
</assembly>
</manifest>
说明:
name:对应程序集名称;
version:对应程序集版本号; 版本号的获取:直接点击被引用的DLL然后单击属性即可看到
publickeytoken:公钥标记(Vistual Studio 命令行工具中通过 sn -T <assemblyName>获取);
relpath:程序集文件全名;
downloadUri:为下载该程序集制定的压缩包,必须为zip压缩文件;可以指定绝对路径,本例为相对路径;
注:如果多个程序集制定的downloadUri相同,则编译系统会将这些程序集压缩到同一个zip文件中
以上步骤就完成了相关配置,现在重新编译整个解决方案,编译成功后,可以在Web项目的ClientBin文件夹中,会发现多出了对应的压缩包(本例为:Microsoft.Windows.Controls.zip)。
另外:可以打开SilverLight的xap文件中的AppManifest.xaml文件,会发现对应的Deployment.ExternalParts部分增加了
<Deployment.ExternalParts>
<ExtensionPart Source="Microsoft.Windows.Controls.zip" />
</Deployment.ExternalParts>
六、总结
用户自定义程序集缓存使用时,也必须 选择"通过使用应用程序库缓存减小XAP大小"。
以上内容参考:http://msdn.microsoft.com/en-us/library/dd833069%2 8VS.95%29.aspx