zoukankan      html  css  js  c++  java
  • 利用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#
  • 相关阅读:
    Kubernetes基本概念之Volume
    Kubernetes对象之PersistentVolume,PersistentVolumeClaim和StorageClass
    SSDB高效能缓存系统
    python2升级python3
    pkg-config相关的常用指令
    CISSP考试经验分享
    如何在命令行添加换行符到git commit -m "xxx"
    为什么tcp-wrappers被Redhat Centos Fedora废弃?
    Docker 国内仓库和镜像
    shell脚本对代码执行时间的计时
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2496750.html
Copyright © 2011-2022 走看看