那么WPF又是什么呢?WPF全名是Windows Presentation Foundation,不知道是不是因为Bill Gates一心投身公益事业,连微软的产品都要加上Foundation。WPF是微软对WinForm的一个全新的发展。WPF的第一个版本是随.NET 3.0发布的,经历了3.5,到现在4.0已经可以说是进入了成熟期了(可以摘掉Beta的名字了,虽然微软本来就没有加上)。相比较其他图形界面API,WPF最大的优势是界面设计和应用逻辑的分离,至少这是微软官方的说法。WPF是一个相对被很多人忽视的东西,这主要是因为在现在互联网的网页时代,有多少人愿意去搞Desktop Application呢?这个问题我不在这里讨论,因为并没有什么讨论的意义。
当我们开始进行WPF编程以后,我们就会发现WPF看似是一个很好用的东西,表面上看,WPF非常友好,MSDN上的很多Example短小精悍,自己模仿起来是很容易的。但是,真个搞起来的时候,我们就会发现,搞好WPF是很难的(当然,什么东西用好都不容易),特别是当我们要做的界面比较复杂的时候,或者说我们要表现的业务逻辑比较复杂的时候。WPF的程序往往开始搞的时候都是很美好的,随着项目的推进,界面的逻辑越来越复杂,程序的质量会直线下降,一直到完全无法维护的程度。那么,WPF到底能不能搞大型项目呢?是不是像WinForm一样一旦做大了就力不从心了呢?
我想微软给了我们很好的答案,那就是Visual Studio 2010,一个基于WPF的大家伙。我相信,我们自己搞的项目不会有Visual Studio那么大,所以我们对WPF是要有信心的。那么,是什么成就了Visual Studio 2010呢?微软告诉我们,是MVVM,这个MVC的发展。我倒是觉得是MEF这个东西。MEF是什么?MEF全名Managed Extensibility Framework,其实就是微软自己的一个拓展架构,像很多人说的那样,一个微软自己的IoC架构。当MEF碰到WPF,就有了我们这一系列文章的正题,那就是可拓展的界面应用程序。
现在看看上面自己写的东西,感觉自己都不知道自己在说什么,舍不得删啊:)这个可拓展的界面应用程序究竟是个什么东西呢?简单来说,就是一个.NET下的像Eclipse一样的东西。Eclipse强大在哪?它是一个界面应用的Host,任何人都可以在上面开发插件,插件的用途可以是千差万别,但是只要你继承了对应的借口,插件就可以在Eclipse里运行。我们在.NET下,就是需要这样的Host。这样,当我们想开发新的东西的时候,就可以直接切入到业务逻辑上,进行插件的开发,没必要考虑很多环境的问题。同时,还可以对以前开发的插件进行代码重用,或者拓展。当然,我是没有本事搞一个像Eclipse那么复杂的东西的,而且我也没有这样的需要。我们真正需要的就是一个简单的可拓展的程序,我们可以把每天零零散散写的程序都变成这个程序的拓展插件,这样可以慢慢积累自己的代码库。要知道,在现在这个编程语言都在拼库的时代,我们自己写的每一行代码都是十分宝贵的,一定不要让他们在硬盘里发霉,要时常拿出来看看。
下面,作为热身,我们做一个简单的关于MEF的小程序。我们先建立一个Console Project,然后添加MEF的Library: System.ComponentModel.Composition.dll.
然后,我们定义一个简单的接口:
- public interface Plugin
- {
- String PluginName { get; set; }
- }
- public class Plugin1 : Plugin
- {
- public String PluginName { get; set; }
- public Plugin1()
- {
- this.PluginName = "Plugin 1";
- }
- }
- public class Plugin2 : Plugin
- {
- public String PluginName { get; set; }
- public Plugin2()
- {
- this.PluginName = "Plugin 2";
- }
- }
下面,我们添加MEF定义。首先我们要加入Using System.ComponentModel.Composition;,当然,如果你有用Resharper的话,请忽略这步,然后:
- [Export(typeof(Plugin))]
- public class Plugin1 : Plugin
- [Export(typeof(Plugin))]
- public class Plugin2 : Plugin
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Reflection;
- using System.ComponentModel.Composition;
- using System.ComponentModel.Composition.Hosting;
- namespace MEFConsoleExample
- {
- class Program
- {
- [ImportMany(typeof(Plugin))]
- public Plugin[] Plugins;
- public Program()
- {
- var result = this.Compose();
- if (result == false)
- {
- return;
- }
- else
- {
- foreach (var plugin in Plugins)
- {
- Console.WriteLine("Plugin name: " + plugin.PluginName);
- }
- }
- }
- static void Main(string[] args)
- {
- var test = new Program();
- }
- private bool Compose()
- {
- var catalog = new AggregateCatalog();
- catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
- var provider = new ComposablePartExportProvider();
- var container = new CompositionContainer(catalog, provider);
- provider.SourceProvider = container;
- var batch = new CompositionBatch();
- batch.AddPart(this);
- try
- {
- container.Compose(batch);
- }
- catch (CompositionException exception)
- {
- Console.WriteLine(exception.ToString());
- return false;
- }
- return true;
- }
- }
- }
Plugin name: Plugin 1
Plugin name: Plugin 2
Press any key to continue . . .
当然,上面的这些只是皮毛中的皮毛,不过今天不想写了,以后再慢慢写吧。