技术开发 频道

VS开发:.NET插件系统实现快速可视化

 public static Object GetObjectInstance(string interfaceName, int index) 封装了的反射实例化方法。 类型参数是接口名称和在插件列表中的位置,为了简化, 类的构造函数必须是没有形参的。

  下面的代码做了详细的说明:

1 /// <summary>
2 /// 该类定义了插件系统通过attribute记录的类基本信息
3 /// </summary>
4 public class ObjectBasicInfo
5 {
6 public string myLogoURL { get; set; }
7 public string myName { get; set; }
8 public Type myType { get; set; }
9 public string myDetail { get; set; }
10 }
11 /// <summary>
12 /// 单例模式提供的插件搜索器
13 /// </summary>
14 public class SingletonProvider
15 {
16 SingletonProvider()
17 {
18 }
19 static Dictionary<string, ObservableCollection<ObjectBasicInfo>> myObjectBasicInfoDictionary = new Dictionary<string, ObservableCollection<ObjectBasicInfo>>();
20
21 public static Object GetObjectInstance(string interfaceName, int index)
22 {
23 return Activator.CreateInstance(GetInstance(interfaceName)[index].myType);
24 }
25 public static ObservableCollection<ObjectBasicInfo> GetInstance(string interfaceName)
26 {
27 if (myObjectBasicInfoDictionary.ContainsKey(interfaceName)) //如果字典中存在该方法,则直接返回结果
28 return myObjectBasicInfoDictionary[interfaceName];
29 else
30 {
31
32 ObservableCollection<ObjectBasicInfo> tc = new ObservableCollection<ObjectBasicInfo>(); //执行查找方法
33
34 Assembly assembly = Assembly.GetCallingAssembly();
35 Type[] types = assembly.GetTypes();
36 foreach (Type type in types)
37 {
38 if (type.GetInterface(interfaceName) != null && !type.IsAbstract)
39 {
40
41
42 // Iterate through all the Attributes for each method.
43 foreach (Attribute attr in
44 type.GetCustomAttributes(typeof(XFrmWorkAttribute), false))
45 {
46 XFrmWorkAttribute attr2 = attr as XFrmWorkAttribute;
47 tc.Add(new ObjectBasicInfo() { myLogoURL = attr2.myResource, myType = type, myDetail = attr2.DetailInfo, myName = attr2.Name });
48 }
49 }
50 }
51 myObjectBasicInfoDictionary.Add(interfaceName, tc);
52 return tc;
53 }
54 }
55
56
57 }

 

  插件搜索器

  使用时非常方便,下面我们会介绍如何使用他。

  4. 使用方法

  下面我们以一个具体场景介绍这一方法的使用: 假设有一个通信系统,要求动态增减通信功能,如USB,串口,WIFI,蓝牙等。 我们将其公共方法为接口ICommMethod ,所有通信方法都必须实现这一接口,并增加自定义的XFrmworkAttribute.

1 [XFrmWorkAttribute("标准蓝牙通信", "ICommMethod", "提供支持绝大多数蓝牙设备的socket蓝牙通信","/XFrmWork.XMove.Comm;component/Images/标准蓝牙.jpg")]
2 public class BluetoothAdvanced : AbstartComm
3 {
4 public BluetoothAdvanced():base
5 ()
6 {
7
8 }
9 }

  其他方法不一一列举。

  我们在一个插件管理类中直接这样调用:

ComMethodList.DataContext = SingletonProvider.GetInstance("ICommMethod");

  ComMethodList是我的系统中一个可用通信方法列表的WPF的Listbox控件。 直接将 ObservableCollection> 集合绑定到该控件的数据上下文中,即可显示当前所有的通信列表。 Listbox中的对应index即插件集合的index,通过上面描述的实例化方法,就能反射实例化之。 讨论WPF的数据绑定超过了本文的范畴,但可查询相关资料。读者可以自行设计和使用该集合提供的数据。显示效果如下图:

  5. 在已实例化的对象中获取该类的attribute数据

  还有一个遗留问题,即在实例化的对象中,我们依旧要获得类的名称,描述和其他相关信息,如何做呢? 我们定义如下的attribute方法实现之

public class AttributeHelper
2 {
3 public static XFrmWorkAttribute GetCustomAttribute(Type source)
4 {
5
6 object[] attributes = source.GetCustomAttributes(typeof(XFrmWorkAttribute), false);
7 foreach (object attribute in attributes)
8 {
9 if (attribute is XFrmWorkAttribute)
10 return (XFrmWorkAttribute)attribute;
11 }
12
13 return new XFrmWorkAttribute("不存在定义","NULL","NULL","无定义资源");
14 }
15 }

  若该类未实现自定义的attribute,返回一个“空”值,提醒设计者或开发人员。

  使用起来也很简单,例如我们想获得该对象的“名称”:

 public string PublicName

  {

  
get { return AttributeHelper.GetCustomAttribute(this.GetType()).Name; }

  }

  注意,属性访问器中,显然只应该实现get方法,它是运行时的不可修改对象。

  6. 其他

  本文的来源是作者项目中的实际需要,不实例化类而获得类的相关信息是一种很普遍的需求,attribute是一种做法,也可以通过xml实现,很多插件系统就是这么做的,但对于轻量级的系统来说,attribute可能更合适,而单例模式的引用给该方法带来了很大的方便。 有任何问题欢迎随时留言交流。

0
相关文章