利用Unity来实现插件开发
论坛里有许多插件开发的文章,本文就不长篇大论了,说一下我的简单思路:
1、建一个IPlugin接口,每个插件都要继承这个接口。
2、建一个插件管理类,利用Unity来管理各个插件。
1 using System.Reflection;
2 using Microsoft.Practices.Unity;
3 public interface IPlugin
4 {
5 void LoadPlugin();
6 string PluginName { get ; }
7 }
8 public class PlugInManage
9 {
10 /// <summary>
11 /// 从dll、exe文件中获取继承IPluin接口的所有类的类型信息
12 /// </summary>
13 /// <param name="path"> 文件路径 </param>
14 /// <returns> 类型信息(插件名称,(插件类名称,插件所在程序集名称)) </returns>
15 public static Dictionary< string , string > Load( string path)
16 {
17 if (! System.IO.Directory.Exists(path))
18 {
19 throw new System.IO.DirectoryNotFoundException();
20 }
21
22 Dictionary< string , string > pluins = new Dictionary< string , string > ();
23 var files = System.IO.Directory.GetFiles(path);
24 foreach ( var file in files)
25 {
26 if (file.ToLower().EndsWith( " .exe " ) || file.ToLower().EndsWith( " .dll " ))
27 {
28 var assembly = Assembly.LoadFrom(file);
29 var types = assembly.GetTypes();
30 foreach ( var type in types)
31 {
32
33 if (type.GetInterfaces().Count(c =>c == typeof (IPlugin)) > 0 )
34 {
35
36 IPlugin instance = assembly.CreateInstance(type.FullName) as IPlugin;
37 if (instance != null )
38 {
39 _container.RegisterType( typeof (IPlugin), type, type.FullName, new ExternallyControlledLifetimeManager());
40
41 var name = string .IsNullOrEmpty(instance.PluginName) ?
42 type.FullName : instance.PluginName;
43 name = pluins.ContainsKey(name)?name+ " _1 " :name;
44 pluins.Add(name, type.FullName);
45 }
46
47 }
48 }
49 }
50 }
51 return pluins;
52 }
53
54 static IUnityContainer _container = new UnityContainer();
55 public static IPlugin Resolve( string name)
56 {
57 GC.Collect();
58 return _container.Resolve<IPlugin> (name);
59 }
60
61 }
3、注意容器内注册的类型应为 ExternallyControlledLifetimeManager类型的生命周期, 外部控制生命周期管理器,这个生命周期管理允许你使用RegisterType和RegisterInstance来注册对象之间的关系,但是其只会对对象保留一个弱引用,其生命周期交由外部控制,也就是意味着你可以将这个对象缓存或者销毁而不用在意UnityContainer,而当其他地方没有强引用这个对象时,其会被GC给销毁掉。在默认情况下,使用这个生命周期管理器,每次调用Resolve都会返回同一对象(单件实例),如果被GC回收后再次调用Resolve方法将会重新创建新的对象。
测试如下:
using XZL.Plugin;
public partial class Form1 : Form
{
Dictionary < string , string > _plugins;
public Form1()
{
InitializeComponent();
this .Load += new EventHandler(Form1_Load);
this .button1.Click += new EventHandler(button1_Click);
}
void button1_Click( object sender, EventArgs e)
{
var p = PlugInManage.Resolve(_plugins[listBox1.SelectedItem.ToString()]);
p.LoadPlugin();
// GC.Collect();
}
void Form1_Load( object sender, EventArgs e)
{
_plugins = PlugInManage.Load(System.IO.Path.GetDirectoryName(Application.ExecutablePath)
+ " \\ " + " plugins " );
foreach ( var item in _plugins)
{
listBox1.Items.Add(item.Key);
}
}
}
1 using XZL.Plugin;
2 public partial class Form1 : Form,IPlugin
3 {
4 public Form1()
5 {
6 InitializeComponent();
7 }
8
9 public void LoadPlugIn()
10 {
11 this .Show();
12 }
13
14
15 string IPlugin.PluginName
16 {
17 get { return this .Text; }
18 }
19 }
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UnityTest
{
using System.Diagnostics;
using System.Windows.Forms;
using Microsoft.Practices.Unity.Configuration;
using Microsoft.Practices.Unity;
using System.Configuration;
public interface IMessage
{
DateTime Time { get ; set ; }
string Text { get ; set ; }
string ToString( string split);
}
public class MyMessage:IMessage
{
public DateTime Time { get ; set ; }
public string Text { get ; set ; }
public MyMessage( string text,DateTime time)
{
Text = text;
Time = time;
}
public MyMessage( string text): this (text,DateTime.Now){}
public string ToString( string split = " \t " )
{
return Time.ToString() + split + Text +split+ GetHashCode();
}
}
public interface ITrace
{
IMessage Message { get ; set ; }
void Write( string message);
}
public class ConsoleTrace:ITrace
{
[Dependency]
public IMessage Message { get ; set ; }
public void Write( string message)
{
if (Message != null )
{
message = Message.ToString( " \t " );
}
Trace.WriteLine(message);
}
}
public class FormTrace:ITrace
{
public IMessage Message { get ; set ; }
public void Write( string message)
{
if (Message != null )
{
message = Message.ToString( " \t " );
}
Trace.WriteLine(message);
}
}
public class Class1
{
public void test1()
{
IUnityContainer container = new UnityContainer();
IUnityContainer childContainter = container.CreateChildContainer();
ExeConfigurationFileMap map = new ExeConfigurationFileMap();
map.ExeConfigFilename = " UnityTest.dll.config " ;
System.Configuration.Configuration config
= ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
UnityConfigurationSection section = (UnityConfigurationSection)config.GetSection( " unity " );
var defultContainter = config.AppSettings.Settings[ " DefultContainter " ].Value;
section.Configure(container, defultContainter);
section.Configure(childContainter, " First " );
// container.LoadConfiguration("Fourth");
// container.RegisterType<ITrace, CosoleTrace>(new ContainerControlledLifetimeManager());
// container.RegisterType<ITrace, FormTrace>();
var message = container.Resolve<IMessage> ();
Trace.WriteLine(message.ToString( " \t " ));
message.Text = " 1111 " ;
var trace = childContainter.Resolve<ITrace> ();
trace.Message = message;
trace.Write( " fdsfds " );
trace = childContainter.Resolve<ITrace> ();
// trace.Message = message;
trace.Write( " fdsfds " );
trace = childContainter.Resolve<ITrace> ();
trace.Write( " fdsfds " );
// container.LoadConfiguration("Second");
// trace = container.Resolve<ITrace>();
// trace.Write("fdsfds");
}
}
}
<?xml version= " 1.0 " encoding= " utf-8 " ?>
<configuration>
<configSections>
<section name = " unity " type = " Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,
Microsoft.Practices.Unity.Configuration " />
</configSections>
<appSettings>
<add key = " DefultContainter " value= " ChildContainter " />
</appSettings>
<unity xmlns = " http://schemas.microsoft测试数据/practices/2010/unity " >
< namespace name= " UnityTest " />
<assembly name= " UnityTest " />
<container name= " ChildContainter " >
<register type= " IMessage " mapTo= " MyMessage " >
<constructor>
<param name= " text " type= " System.String " value= " abc " />
</constructor>
</register>
</container>
<container name= " First " >
<register type= " ITrace " mapTo= " ConsoleTrace " >
<lifetime type= " singleton " />
</register>
</container>
<container name= " Second " >
<register type= " ITrace " mapTo= " FormTrace " >
<lifetime type= " singleton " />
</register>
</container>
<container name= " Third " >
<register type= " ITrace " mapTo= " ConsoleTrace " >
<lifetime type= " perresolve " />
</register>
</container>
<container name= " Fourth " >
<register type= " ITrace " mapTo= " ConsoleTrace " >
<lifetime type= " perthread " />
</register>
</container>
</unity>
</configuration>
配置Unity有两种方法:利用配置文件配置;在程序代码中配置。
以 The Unity StopLight QuickStart为例:
在程序中用代码配置,这种方法重新配置需重新编译程序。
IUnityContainer container = new UnityContainer()
.AddNewExtension <SimpleEventBrokerExtension> ();
.RegisterType <ILogger, TraceLogger> ()
.RegisterType <IStoplightTimer, RealTimeTimer>();
另一种方式是利用配置文件配置:配置文件配置是应添加
xmlns = " http://schemas.microsoft测试数据/practices/2010/unity ",这样可以利用xsd架构来智能感知。
<configSections>
<section name = " unity " type = " Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,
Microsoft.Practices.Unity.Configuration " />
</configSections>
<unity xmlns = " http://schemas.microsoft测试数据/practices/2010/unity " >
< namespace name= " StopLight.ServiceInterfaces " />
< namespace name= " StopLight.ServiceImplementations " />
< namespace name= " StopLight.UI " />
< namespace name= " StopLight.Logic " />
<assembly name= " StopLight " />
<container>
<register type= " ILogger " mapTo= " TraceLogger " />
<register type= " IStoplightTimer " mapTo= " RealTimeTimer " />
<register type= " Stoplight " >
<property name= " Logger " dependencyType= " ILogger " dependencyName= " TraceLogger " />
</register>
<register type= " StoplightSchedule " >
<property name= " Logger " dependencyType= " ILogger " dependencyName= " TraceLogger " />
</register>
<register type= " StoplightPresenter " >
<property name= " Stoplight " dependencyType= " Stoplight " dependencyName= " Stoplight " />
<property name= " Schedule " dependencyType= " StoplightSchedule " dependencyName= " StoplightSchedule " />
</register>
</container>
</unity>
IUnityContainer container = new UnityContainer();
UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection( " unity " );
section.Configure(container);
分类: .net , C#
作者: Leo_wl
出处: http://HdhCmsTestcnblogs测试数据/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息声明:本文来自网络,不代表【好得很程序员自学网】立场,转载请注明出处:http://haodehen.cn/did49084