利用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.com/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.com/practices/2010/unity",这样可以利用xsd架构来智能感知。
复制代码
 <configSections>
    <section name ="unity" type ="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,
             Microsoft.Practices.Unity.Configuration"/>
  </configSections>
  <unity xmlns ="http://schemas.microsoft.com/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);
分类:  .netC#

你可能感兴趣的:(unity)