最近C#项目遇到一个问题,我编写了一个开机启动的服务,有两个目的:
(1)客户端运行时需要用到一些缓存,但是这些缓存的加载(从服务器端获取)有些耗时,所以就想要开启一个服务在客户端打开之前就开始获取这些缓存,等到客户端启动的时候将这些缓存通过命名管道传递给他。 这些缓存包括数据字典,用户信息,等等,以后可能还会有更多的缓存;
(2)后台运行的一个客户端代理服务的界面(托盘形式)需要显示这些缓存当前的状态,比如数据字典有多少,是否正常,刷新时间是多少等等。我们的这个windows服务就在获取了缓存之后构造出缓存状态信息通过命名管道传递给这个托盘让它来显示。
问题是我们目前虽然已经确定了有数据字典缓存,但是以后可能还会增加新的缓存,不可能每次增加一种缓存,我们都修改编写的这个服务,添加获取新类型缓存的代码,以后构造其状态信息结构的代码。
所以为了可拓展性,我决定这样做:
(1)为所有缓存获取者编写一个接口ICacheGetter,包含方法DataSet getCache() ; 以后增加新的缓存的时候,就让其他人编写新的缓存获取类继承自这个接口;
(2)针对缓存状态信息构造,也定义这样一个接口ICacheStatInfoBuilder,包含一个方法string buildCacheStatStr(DataSet cache); 将缓存作为参数传递进去,让其他人编写根据缓存内容构造缓存状态信息描述字符串的方法的实现;
所有的缓存获取者(ICacheGetter实现类)都需要将自己配置到一个配置文件中,同样所有的缓存状态信息构造者(ICacheStatInfoBuilder实现类)也需要将自己配置到对应的配置文件中。
然后我的服务只需要负责:
(1)通过XMLDocument类来读取配置文件,通过反射机制实例化所有的缓存获取者,并调用它的缓存获取方法,并将获取的DataSet存放到Dictionary<string,DataSet>中,通过命名管道将这个存储了所有缓存的容器发送给客户端;
(2)通过XMLDocument类来读取配置文件,通过反射机制实例化所有的缓存信息构造者,并调用它的缓存状态信息构造方法,并将构造好缓存状态信息描述字符串存放到Dictionary<string,string>中,通过命名管道将这个存储了所有缓存状态信息字符串的容器发送给托盘;
(PS:应该也可以用注册/通知,或者说订阅/发布的模式来实现)
想好之后我就准备开始动手了,没想到和头儿沟通之后,发现可以用非常简单的方式来解决我的这个问题,没错,就是MEF。
使用EMF解决这个问题大概是要做以下步骤 :
1 所有的缓存获取者/缓存状态信息构造者 都将自己Export出来;
2 在windows服务中申明一个类型为ICacheGetter/ICacheStatInfoBuilder的列表容器;
3 调用一段代码(从官网拷贝),这段代码的作用就是扫描所有的指定目录下面的dll,找到申明了Export的类之后,将它的实例注入到对应的2中申明的容器中;
OK,这样你就可以直接迭代容器,访问其中的对象,调用其方法了,很简单啊有木有!
这个应该就和Java总Spring的依赖注入一个原理,通过加载dll,利用反射技术创建类对象,注入到对应的容器中。
关于更多MEF的信息请查看:http://msdn.microsoft.com/zh-cn/library/vstudio/dd460648.aspx
(转载请注明出处,jiq)
Managed Extensibility Framework 或 MEF 是一个用于创建可扩展的轻型应用程序的库。 应用程序开发人员可利用该库发现并使用扩展,而无需进行配置。 扩展开发人员还可以利用该库轻松地封装代码,避免生成脆弱的硬依赖项。 通过 MEF,不仅可以在应用程序内重用扩展,还可以在应用程序之间重用扩展。