最近做了一个简单的Silverlight插件功能,大致样式仿照IE的插件管理。
想法简陋,敬请指教。
一开始,我想着可以仿照游戏客户端读取插件的方法来做:1.从某一特定的文件夹,如Interface文件夹中读取配置文件及对应的插件文件;2.按照特定的格式解译插件文件。不过在用Silverlight的时候,问题在于:剑三游戏客户端是可以访问本地文件的,而Silverlight不可以。Silverlight本地允许访问的只有IsolatedStorage。于是最终形成的方案变成:1.制订插件接口;2.对应于接口的插件实现文件存放在网络上;3.IsolatedStorage中建立一个列表文件用于存放插件文件地址;4.程序启动时根据IsolatedStorage中的列表文件存储地址读取插件文件。
1.制订插件接口IExtension:
1 public interface IExtension
2 {
3 //Name for the Extension
4 string Name { get; }
5 //Description of the Extension
6 string Description { get; }
7 //The uri address of the Extension
8 string UriForExtension { get; set; }
9 //The icon of the Extension to show in the Extension Management
10 ImageSource IconSource { get; }
11 //The context to pass into the Extension (the hyper links, the texts or so)
12 string Context { get; set; }
13 //The Mouse Event arisen by click the Extension's item when the Extension is integrated to contextMenu
14 MouseButtonEventHandler LeftMouseButtonUp { get; }
15 }
2.主程序启动时读取IsolatedStorage中的列表
1 /// <summary>
2 /// Read Uris From IsolatedStorage
3 /// </summary>
4 /// <param name="fileName">The name defined to save the uris</param>
5 /// <returns></returns>
6 List<string> ReadUriFromFile(string fileName)
7 {
8 List<string> uriList = new List<string>();
9 try
10 {
11 using (IsolatedStorageFile isolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication())
12 {
13 if (isolatedStorageFile.FileExists(fileName))
14 {
15 using (IsolatedStorageFileStream stream = isolatedStorageFile.OpenFile(fileName, FileMode.Open))
16 {
17 StreamReader reader = new StreamReader(stream);
18 while (!reader.EndOfStream)
19 {
20 uriList.Add(reader.ReadLine());
21 }
22 reader.Close();
23 }
24 }
25 }
26 }
27 catch (Exception)
28 {
29
30 }
31 return uriList;
32 }
3.获取每个Extension.dll中对应的数据时用到了MEF。MEF的详细介绍可参见《MEF程序设计指南》博文汇总。
这里MEF的实现步骤以ExtensionOne.dll的实现及读取为例。
①ExtensionOne.dll的实现中使用MEF的[Export (typeof(IExtension))]属性来标识导出的类。
整个ExtensionOne类的实现如下:
1 using System;
2 using System.ComponentModel.Composition;
3 using System.Windows;
4 using System.Windows.Input;
5 using System.Windows.Media;
6 using System.Windows.Media.Imaging;
7 using ExtensionInterface;
8
9 namespace ExtensionOne
10 {
11 [Export (typeof(IExtension))]
12 public class ExtensionOne:IExtension
13 {
14
15 public string Name
16 {
17 get
18 {
19 return "ShowText";
20 }
21 }
22 public string Description
23 {
24 get
25 {
26 return "Show the Text of the Text Control you pressed.";
27 }
28 }
29
30 public ImageSource IconSource
31 {
32 get
33 {
34 return new BitmapImage(
35 new Uri(
36 "One.png",
37 UriKind.Relative));
38 }
39 }
40
41 private string uriForExtension = "";
42 public string UriForExtension
43 {
44 get
45 {
46 return uriForExtension;
47 }
48 set
49 {
50 uriForExtension = value;
51 }
52 }
53
54 private string context="";
55 public string Context
56 {
57 get
58 {
59 return context;
60 }
61 set
62 {
63 context = value;
64 }
65 }
66
67 public MouseButtonEventHandler LeftMouseButtonUp
68 {
69 get
70 {
71 return (s, e) =>
72 {
73 //Here is what exactly this extension functions
74 MessageBox.Show(context, "What You Clicked", MessageBoxButton.OK);
75 };
76
77 }
78 }
79 }
80 }
②在主程序中利用MEF的[Import(typeof(IExtension))]属性来标识导入的类,利用步骤1中获得的ExtensionOne.dll的地址来读取ExtensionOne.dll中ExtensionOne的属性与方法。具体实现如下。
1 private List<IExtension> extensionDllCollections = new List<IExtension>();
2
3 [Import(typeof(IExtension))]
4 public IExtension myExtension
5 {
6 get; set;
7 }
8
9
10 /// <summary>
11 /// Load the IExtension from dll
12 /// </summary>
13 /// <param name="urlString">The url retrieved from the IsolatedStorage</param>
14 private void loadDll(string urlString) {
15 //Load dlls from assembly
16 WebClient client = new WebClient();
17 client.OpenReadCompleted += (s1, e1) =>
18 {
19 try
20 {
21 //Read from DLLs
22 AssemblyPart part = new AssemblyPart();
23 Assembly assembly = part.Load(e1.Result);
24 AssemblyCatalog assemblyCatalog = new AssemblyCatalog(assembly);
25 CompositionContainer compositionContainer =
26 new CompositionContainer(assemblyCatalog);
27 compositionContainer.ComposeParts(this);
28 myExtension.UriForExtension = urlString;
29 extensionDllCollections.Add(myExtension);
30 }
31 catch (Exception exception)
32 {
33
34 }
35 };
36
37 Uri uri = new Uri(urlString, UriKind.RelativeOrAbsolute);
38 client.OpenReadAsync(uri);
39 }
③遍历了所有地址后,所有的IExtension就都存入了extensionDllCollections中了。接下来无论是要将其放入右键菜单还是要进行管理就都方便了。
4.管理Extensions
Extension的管理也模仿了浏览器的插件管理。实现效果如下图。
当前的添加Extensions只实现了简单的通过输入网址来获取插件。
这项工作基本告一段落,多多少少有些收获。回头想来,思路真TM简单。做个记录,也请偶尔路过的能给以指教一二。