Esempio n. 1
0
        /// <summary>
        /// 查找类型
        /// </summary>
        /// <param name="assignTypeFrom">指定的类型</param>
        /// <param name="assemblies">程序集集合</param>
        /// <param name="onlyConcreteClasses">是否仅持续具体的实现类,不查询抽象类</param>
        /// <returns>结果</returns>
        public IEnumerable <Type> FindClassesOfType(Type assignTypeFrom, IEnumerable <Assembly> assemblies, bool onlyConcreteClasses = true)
        {
            var result = new List <Type>();

            try
            {
                foreach (var a in assemblies)
                {
                    Type[] types = null;
                    try
                    {
                        types = a.GetTypes();
                    }
                    catch
                    {
                        //Entity Framework 6 doesn't allow getting types (throws an exception)
                        if (!ignoreReflectionErrors)
                        {
                            throw;
                        }
                    }
                    if (types != null)
                    {
                        foreach (var t in types)
                        {
                            if (assignTypeFrom.IsAssignableFrom(t) || (assignTypeFrom.IsGenericTypeDefinition && DoesTypeImplementOpenGeneric(t, assignTypeFrom)))
                            {
                                if (!t.IsInterface)
                                {
                                    if (onlyConcreteClasses)
                                    {
                                        if (t.IsClass && !t.IsAbstract)
                                        {
                                            result.Add(t);
                                        }
                                    }
                                    else
                                    {
                                        result.Add(t);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            catch (ReflectionTypeLoadException ex)
            {
                var msg = string.Empty;
                foreach (var e in ex.LoaderExceptions)
                {
                    msg += e.Message + Environment.NewLine;
                }

                var fail = new MapleException(msg, ex);
                Debug.WriteLine(fail.Message, fail);

                throw fail;
            }
            return(result);
        }
Esempio n. 2
0
        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="applicationPartManager">Application part manager</param>
        /// <param name="config">Config</param>
        public static void Initialize(ApplicationPartManager applicationPartManager, MapleConfig config)
        {
            // *********************************************************************************************************************************
            //
            // ApplicationPartManager 用途:剥离 Controller 到其他程序集中
            //
            //MVC 框架启动的时候,首先会把 Assembly 程序集转换为 ApplicationPart 添加到 ApplicationPartManager 对象列表中,才能执行后续的任务,
            //因为要从这些程序集中查找 Controller,那么从这个特性我们可以延伸到, 利用此功能,我们可以从 Web 层剥离 Controller 到其他程序集中
            //
            // *********************************************************************************************************************************

            Check.NotNull(applicationPartManager, nameof(applicationPartManager));
            Check.NotNull(config, nameof(config));

            using (new WriteLockDisposable(Locker))
            {
                // TODO: Add verbose exception handling / raising here since this is happening on app startup and could
                // prevent app from starting altogether
                var pluginFolder = new DirectoryInfo(CommonHelper.MapPath(PluginsPath));        //获取插件集合所在目录
                _shadowCopyFolder = new DirectoryInfo(CommonHelper.MapPath(ShadowCopyPath));    //获取插件集合中Bin所在目录

                //已加载的插件集合
                var referencedPlugins = new List <PluginDescriptor>();
                //不兼容或无法加载的插件集合
                var incompatiblePlugins = new List <string>();

                try
                {
                    //从读取installedPlugins.json中读取已加载的插件清单
                    var installedPluginSystemNames = GetInstalledPluginNames(CommonHelper.MapPath(InstalledPluginsFilePath));

                    Debug.WriteLine("查询现有的插件,并将插件对应的DLL移至Bin目录中");
                    //确保 /Plugins 已经存在
                    Directory.CreateDirectory(pluginFolder.FullName);
                    //确保 /Plugins/bin 已经存在
                    Directory.CreateDirectory(_shadowCopyFolder.FullName);

                    //获取 /Plugins/bin 目录中所有的文件清单(包含子目录)
                    var binFiles = _shadowCopyFolder.GetFiles("*", SearchOption.AllDirectories);
                    if (config.ClearPluginShadowDirectoryOnStartup)
                    {
                        //否清理 /Plugins/bin 目录
                        foreach (var f in binFiles)
                        {
                            if (f.Name.Equals("placeholder.txt", StringComparison.InvariantCultureIgnoreCase))
                            {
                                continue;
                            }

                            Debug.WriteLine("移除 " + f.Name);
                            try
                            {
                                //ignore index.htm
                                var fileName = Path.GetFileName(f.FullName);
                                if (fileName.Equals("index.htm", StringComparison.InvariantCultureIgnoreCase))
                                {
                                    continue;
                                }

                                File.Delete(f.FullName);
                            }
                            catch (Exception exc)
                            {
                                Debug.WriteLine("移除文件 " + f.Name + " 失败. 错误描述: " + exc);
                            }
                        }
                    }

                    //加载查询的描述性信息
                    foreach (var dfd in GetDescriptionFilesAndDescriptors(pluginFolder))
                    {
                        var descriptionFile  = dfd.Key;     //插件描述性信息所对应的文件
                        var pluginDescriptor = dfd.Value;   //插件描述性信息实体类

                        //确保插件的版本有效
                        if (!pluginDescriptor.SupportedVersions.Contains(MapleVersion.CurrentVersion, StringComparer.InvariantCultureIgnoreCase))
                        {
                            incompatiblePlugins.Add(pluginDescriptor.SystemName);
                            continue;
                        }

                        //信息验证
                        if (string.IsNullOrWhiteSpace(pluginDescriptor.SystemName))
                        {
                            throw new MapleException($"未设置插件 '{descriptionFile.FullName}' 名称. 请给插件定义唯一的名称再重新编译.");
                        }
                        if (referencedPlugins.Contains(pluginDescriptor))
                        {
                            throw new MapleException($"插件 '{pluginDescriptor.SystemName}' 名称已经存在,请给插件定义唯一的名称再重新编译");
                        }

                        //判断插件是否已经被安装
                        pluginDescriptor.Installed = installedPluginSystemNames
                                                     .FirstOrDefault(x => x.Equals(pluginDescriptor.SystemName, StringComparison.InvariantCultureIgnoreCase)) != null;

                        try
                        {
                            if (descriptionFile.Directory == null)
                            {
                                throw new MapleException($"Directory cannot be resolved for '{descriptionFile.Name}' description file");
                            }

                            //确保插件所需的DLL在 plugins/bin 目录中存在,如果不存在则拷贝过去
                            var pluginFiles = descriptionFile.Directory.GetFiles("*.dll", SearchOption.AllDirectories)
                                              //just make sure we're not registering shadow copied plugins
                                              .Where(x => !binFiles.Select(q => q.FullName).Contains(x.FullName))
                                              .Where(x => IsPackagePluginFolder(x.Directory))
                                              .ToList();

                            //查询插件所对应的DLL文件
                            var mainPluginFile = pluginFiles
                                                 .FirstOrDefault(x => x.Name.Equals(pluginDescriptor.AssemblyFileName, StringComparison.InvariantCultureIgnoreCase));

                            //如果插件所在文件不存在,则忽略
                            if (mainPluginFile == null)
                            {
                                incompatiblePlugins.Add(pluginDescriptor.SystemName);
                                continue;
                            }

                            pluginDescriptor.OriginalAssemblyFile = mainPluginFile;

                            //执行插件部署
                            pluginDescriptor.ReferencedAssembly = PerformFileDeploy(mainPluginFile, applicationPartManager, config);
                            //拷贝插件所需但尚未加载的DLL
                            foreach (var plugin in pluginFiles
                                     .Where(x => !x.Name.Equals(mainPluginFile.Name, StringComparison.InvariantCultureIgnoreCase))
                                     .Where(x => !IsAlreadyLoaded(x)))
                            {
                                PerformFileDeploy(plugin, applicationPartManager, config);
                            }

                            //初始化插件类型
                            foreach (var t in pluginDescriptor.ReferencedAssembly.GetTypes())
                            {
                                if (typeof(IPlugin).IsAssignableFrom(t))
                                {
                                    if (!t.IsInterface)
                                    {
                                        if (t.IsClass && !t.IsAbstract)
                                        {
                                            pluginDescriptor.PluginType = t;
                                            break;
                                        }
                                    }
                                }
                            }

                            referencedPlugins.Add(pluginDescriptor);
                        }
                        catch (ReflectionTypeLoadException ex)
                        {
                            //插件加载失败,抛出异常
                            var msg = $"Plugin '{pluginDescriptor.FriendlyName}'. ";
                            foreach (var e in ex.LoaderExceptions)
                            {
                                msg += e.Message + Environment.NewLine;
                            }

                            var fail = new Exception(msg, ex);
                            throw fail;
                        }
                        catch (Exception ex)
                        {
                            //插件加载失败,抛出异常
                            var msg = $"Plugin '{pluginDescriptor.FriendlyName}'. {ex.Message}";

                            var fail = new MapleException(msg, ex);
                            throw fail;
                        }
                    }
                }
                catch (Exception ex)
                {
                    var msg = string.Empty;
                    for (var e = ex; e != null; e = e.InnerException)
                    {
                        msg += e.Message + Environment.NewLine;
                    }

                    var fail = new MapleException(msg, ex);
                    throw fail;
                }

                ReferencedPlugins   = referencedPlugins;
                IncompatiblePlugins = incompatiblePlugins;
            }
        }