好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

利用Unity来实现插件开发

利用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); 

分类:  .net ,  C#

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于利用Unity来实现插件开发的详细内容...

  阅读:42次