首页 > 代码库 > LCLFramework框架之Plugin模式

LCLFramework框架之Plugin模式

Plugin模式在示例中的实际目的小结一下


  1. Plugin模式是架构模式,在设计架构时,才有参考价值;
  2. Plugin模式主要是实现单一职责的封装,和扩展应用程序;

Plugin与扩展的区别


      插件稍不同于扩展(extension),插件通常依赖于主应用程序的接口,有一个它们可以运行的确定的界限。扩展则通常有更少的限制,也可以提供它们自己的接口。相同的是,它们通常都用来减少主应用程序的大小、提供一些可选的功能。

       这里不得不提到Mozilla Firefox 和相关软件。它们使用一个叫做Add-on的名词,Add-on又被细分为插件、主题(theme)、搜索引擎(search engine)和扩展。在以后的文章中将会提到Mozilla插件和古老的NPAPI的渊源,以及firefox中插件和扩展的区别。

LCLFramework框架之Plugin设计


LCLFramework框架之Plugin模式主要是参考http://www.cnblogs.com/zgynhqf/p/3356692.html框架来的。

clipboard

LCLFramework框架之Plugin模式设计代码


   /// <summary>

    /// 插件定义。

    /// </summary>

    public interface IPlugin

    {

        /// <summary>

        /// 插件的启动级别

        /// </summary>

        int SetupLevel { get; }

        /// <summary>

        /// 插件的初始化方法。

        /// 框架会在启动时根据启动级别顺序调用本方法。

        ///

        /// 方法有两个职责:

        /// 1.依赖注入。

        /// 2.注册 app 生命周期中事件,进行特定的初始化工作。

        /// </summary>

        /// <param name="app">应用程序对象。</param>

        void Initialize(IApp app);

    }

    public abstract class LCLPlugin : IPlugin

    {

        /// <summary>

        /// 插件的启动级别。

        /// </summary>

        protected virtual int SetupLevel

        {

            get { return ReuseLevel.Main; }

        }

        /// <summary>

        /// 插件的初始化方法。

        /// 框架会在启动时根据启动级别顺序调用本方法。

        /// 方法有两个职责:

        /// 1.依赖注入。

        /// 2.注册 app 生命周期中事件,进行特定的初始化工作。

        /// </summary>

        /// <param name="app">应用程序对象。</param>

        public abstract void Initialize(IApp app);

        int IPlugin.SetupLevel

        {

            get { return this.SetupLevel; }

        }

    }

   /// <summary>

    /// 表示某一个插件程序集

    /// </summary>

    [DebuggerDisplay("{Assembly.FullName}")]

    public class PluginAssembly

    {

        public static readonly IPlugin EmptyPlugin = new _EmptyPlugin();

        public PluginAssembly(Assembly assembly, IPlugin instance)

        {

            this.Instance = instance;

            this.Assembly = assembly;

        }

        /// <summary>

        /// 程序集当中的插件对象。

        /// 如果插件中没有定义,则此属性为 null。

        /// </summary>

        public IPlugin Instance { get; private set; }

        /// <summary>

        /// 程序集本身

        /// </summary>

        public Assembly Assembly { get; private set; }

        private class _EmptyPlugin : LCLPlugin

        {

            protected override int SetupLevel

            {

                get { return PluginSetupLevel.System; }

            }

            public override void Initialize(IApp app)

            {

                //TODO:组件初始化

                var plugins = LEnvironment.GetAllPlugins();

                foreach (var plugin in plugins)

                {

                    DomainServiceLocator.TryAddAssemblyService(plugin.Assembly);

                }

            }

        }

    }

    /// <summary>

    /// 插件环境

    /// PluginEnvironment

    /// </summary>

    public partial class LEnvironment

    {

        private const string DomainPluginFolder = "Library";

        #region 启动 Plugins

        private static bool _initialized;

        private static void CheckUnInit()

        {

            if (_initialized) throw new NotSupportedException("框架已经初始化完成!");

        }

        internal static void NotifyIntialized()

        {

            _initialized = true;

        }

        /// <summary>

        /// 启动所有的 插件

        /// </summary>

        /// <param name="app"></param>

        internal static void StartupPlugins()

        {

            CheckUnInit();

            var libraries = GetAllPlugins();

            foreach (var pluginAssembly in libraries)

            {

                //调用 ILibrary

                var library = pluginAssembly.Instance as LCLPlugin;

                if (library != null) library.Initialize(_appCore);

            }

        }

        #endregion

        #region 获取所有 Plugins

        private static IEnumerable<PluginAssembly> _libraries;

        /// <summary>

        /// 获取当前环境被初始化的所有插件。

        /// </summary>

        /// <returns></returns>

        public static IEnumerable<PluginAssembly> GetAllPlugins()

        {

            return GetDomainPlugins().Union(GetUIPlugins()).OrderBy(a => a.Instance.SetupLevel);

        }

        public static Assembly[] GetAllPluginAssemblys()

        {

            var plugAssembly = GetAllPlugins().ToArray();

            Assembly[] list = new Assembly[plugAssembly.Count()];

            for (int i = 0; i < plugAssembly.Count(); i++)

            {

                list[i] = plugAssembly[i].Assembly;

            }

            return list;

        }

        /// <summary>

        /// 找到当前程序所有可运行的领域实体插件。

        /// </summary>

        /// <returns></returns>

        public static IEnumerable<PluginAssembly> GetDomainPlugins()

        {

            if (_libraries == null)

            {

                var assemblies = EnumerateAllDomainAssemblies().Union(PluginTable.Libraries).ToArray();

                _libraries = LoadPlugins(assemblies);

                PluginTable.Libraries.Lock();

            }

            return _libraries;

        }

        private static IEnumerable<Assembly> EnumerateAllDomainAssemblies()

        {

            yield return LoadLCLAssembly("LCL");

            foreach (var file in EnumerateAllDomainPluginFiles())

            {

                yield return Assembly.LoadFrom(file);

            }

        }

        private static IEnumerable<string> EnumerateAllDomainPluginFiles()

        {

            //查找Library目录下的所有程序集

            string libraryPath = MapDllPath(DomainPluginFolder + "\\");

            if (Directory.Exists(libraryPath))

            {

                foreach (var dll in Directory.GetFiles(libraryPath, "*.dll"))

                {

                    yield return dll;

                }

            }

        }

        private static Assembly LoadLCLAssembly(string name)

        {

            var aName = typeof(LEnvironment).Assembly.GetName();

            aName.Name = name;

            return Assembly.Load(aName);

        }

        /// <summary>

        /// 找到当前程序所有可运行的界面插件程序集。

        /// </summary>

        /// <returns></returns>

        public static IEnumerable<PluginAssembly> GetUIPlugins()

        {

            return Enumerable.Empty<PluginAssembly>();

        }

        private static List<PluginAssembly> LoadPlugins(IEnumerable<Assembly> assemblies)

        {

            return assemblies.Select(assembly =>

            {

                var pluginType = assembly.GetTypes().FirstOrDefault(t => typeof(IPlugin).IsAssignableFrom(t) && !t.IsInterface && !t.IsAbstract);

                IPlugin pluginInstance = PluginAssembly.EmptyPlugin;

                if (pluginType != null)

                {

                    pluginInstance = Activator.CreateInstance(pluginType) as IPlugin;

                }

                return new PluginAssembly(assembly, pluginInstance);

            })

                //这里按照产品 721 进行排序。

            .OrderBy(a => a.Instance.SetupLevel)

            .ToList();

        }

        #endregion

        #region RootType

        private static List<Type> _allRootTypes;

        /// <summary>

        /// 遍历系统中存在的所有聚合根类型

        /// </summary>

        /// <returns></returns>

        internal static IList<Type> GetAllRootTypes()

        {

            if (_allRootTypes == null)

            {

                var result = new List<Type>();

                foreach (var plugin in GetAllPlugins())

                {

                    foreach (var type in plugin.Assembly.GetTypes())

                    {

                        if (IsRootType(type)) result.Add(type);

                    }

                }

                _allRootTypes = result;

            }

            return _allRootTypes;

        }

        internal static bool IsRootType(Type entityType)

        {

            if (entityType.BaseType == typeof(DomainEntity))

                return true;

            else

                return false;

        }

        #endregion

    }

   /// <summary>

    /// 使用代码添加的插件程序集。

    /// 只是以插件机制加载,但本质上是必需的,并非插件。

    /// </summary>

    public class PluginTable : Collection<Assembly>

    {

        private static PluginTable _domainLibraries = new PluginTable();

        /// <summary>

        /// 已经添加的实体插件程序集。

        /// </summary>

        public static PluginTable Libraries

        {

            get { return _domainLibraries; }

        }

        /// <summary>

        /// 直接添加一个插件对应的程序集引用。

        /// </summary>

        /// <typeparam name="TPlugin"></typeparam>

        public void AddPlugin<TPlugin>()

            where TPlugin : IPlugin

        {

            this.Add(typeof(TPlugin).Assembly);

        }

        private bool _locked;

        protected override void ClearItems()

        {

            this.EnsureWritable();

            base.ClearItems();

        }

        protected override void RemoveItem(int index)

        {

            this.EnsureWritable();

            base.RemoveItem(index);

        }

        protected override void InsertItem(int index, Assembly item)

        {

            if (!this.Contains(item))

            {

                this.EnsureWritable();

                base.InsertItem(index, item);

            }

        }

        protected override void SetItem(int index, Assembly item)

        {

            if (!this.Contains(item))

            {

                this.EnsureWritable();

                base.SetItem(index, item);

            }

        }

        internal void Lock()

        {

            this._locked = true;

        }

        private void EnsureWritable()

        {

            if (this._locked) throw new InvalidOperationException("集合不可再变更。");

        }

    }

    /// <summary>

    /// 产品的 “721” 重用级别

    /// </summary>

    public static class ReuseLevel

    {

        /// <summary>

        /// 主版本(7)

        /// </summary>

        public const int Main = 100;

        /// <summary>

        /// 部分版本(2)

        /// </summary>

        public const int Part = 200;

        /// <summary>

        /// 客户化版本(1)

        /// </summary>

        public const int Customized = 300;

    }

    /// <summary>

    /// LCL 中的其它插件启动级别。

    /// </summary>

    public static class PluginSetupLevel

    {

        /// <summary>

        /// LCL 系统级别的重用级别,一般不要使用。

        /// </summary>

        public const int System = -1;

    }

LCLFramework框架之Plugin开发


clipboard[1]

clipboard[2]

LCLFramework框架之Plugin模式