• NetCore插件化开发


    使用NetCore3.1完成框架基本开发后实际应用于项目,需要保证框架的独立性与项目的个性化, 就需要类似于下图的插件化形式将项目放入框架这个容器中启动,下面开始详细介绍实现步骤

    项目dll扫描

    在框架根目录创建Plugin文件夹,项目在生成后事件使用copy命令拷贝至Plugin文件夹,框架启动时会扫描该文件夹并进行ShadowCopy到PluginTemplate文件夹中

       private static void ScanPlugin()
            {
                if (!PluginFolder.Exists)
                {
                    PluginFolder.Create();
                }
                if (!TempPluginFolder.Exists)
                {
                    TempPluginFolder.Create();
                }
    
                TempPluginFolder.Attributes = FileAttributes.Normal & FileAttributes.Directory;
                PluginFolder.Attributes = FileAttributes.Normal & FileAttributes.Directory;
                //清理临时文件。
                foreach (var file in TempPluginFolder.GetFiles("*.dll", SearchOption.AllDirectories))
                {
                    try
                    {
                        File.SetAttributes(file.FullName, FileAttributes.Normal);
                        file.Delete();
                    }
                    catch (Exception e)
                    {
                        throw new Exception("请检查IIS权限");
                    }
    
                }
                //复制插件进临时文件夹。
                foreach (var plugin in PluginFolder.GetFiles("*.dll", SearchOption.AllDirectories))
                {
                    try
                    {
                        string CopyFilePath = Path.Combine(TempPluginFolder.FullName, plugin.Name);
                        File.Copy(plugin.FullName, CopyFilePath, true);
                        File.SetAttributes(CopyFilePath, FileAttributes.Normal);
                    }
                    catch (Exception e)
                    {
                        throw new Exception("请检查IIS权限");
                    }
                }
            }

    项目dll加载

    直接使用ApplicationParts加载AssemblyPart即可

         public static void LoadPlugin()
            {
                ScanPlugin();
                IEnumerable<Assembly> AssemblyList = GetPluginAssemblies();
                foreach (Assembly assembly in AssemblyList)
                {
                    foreach (var type in assembly.GetTypes())
                    {
                        if (type.IsAssignableFrom(typeof(Controller)) && type.Name.Contains("Controller") && type.IsClass && !type.IsAbstract)
                        {
                            string Name = type.Name;
                            //如果有自定义的路由注解
                            if (type.IsDefined(typeof(Route), false))
                            {
                                var areaattribute = type.GetCustomAttributes(typeof(Route), false).FirstOrDefault();
                                Name = ((Route)areaattribute).Name;
                                Name += "Controller";
    
                            }
                            if (!ControllerTypeDic.ContainsKey(Name))
                            {
                                ControllerTypeDic.Add(Name, type);
                            }
                        }
                    }
                    var controllerAssemblyPart = new AssemblyPart(assembly);
                    CloudUtil.GetBuilder().ConfigureApplicationPartManager(apm =>
                    {
                        apm.ApplicationParts.Add(controllerAssemblyPart);
                    });
                }
                CloudUtil.GetBuilder().SetCompatibilityVersion(CompatibilityVersion.Version_3_0);
                StartPluginRefreshWatch();
            }

    项目视图

    项目的cshtml视图文件可以手动拷贝到部署的框架Views文件夹中(正式环境),也可以通过监控当前项目的Views文件夹,如果变动进行自动拷贝(开发环境)

      private static void StartPluginRefreshWatch()
            {
                _FileSystemWatcher.Path = CloudUtil.GetContentPath() + "/Plugin";
                _FileSystemWatcher.Filter = "*.dll";
                _FileSystemWatcher.Changed += _FileSystemWatcher_Changed;
    
                _FileSystemWatcher.IncludeSubdirectories = true;
                _FileSystemWatcher.NotifyFilter =
                    NotifyFilters.Attributes | NotifyFilters.CreationTime | NotifyFilters.DirectoryName | NotifyFilters.FileName | NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.Security | NotifyFilters.Size;
                _FileSystemWatcher.EnableRaisingEvents = true;
    
                if (AppConfigUtil.Configuration["Frame:ViewsPublishType"]=="AutoCopy"
                    && !string.IsNullOrEmpty(AppConfigUtil.Configuration["Frame:ViewsVirtualPath"]) 
                    && Directory.Exists(AppConfigUtil.Configuration["Frame:ViewsVirtualPath"]))
                {
                    FileSystemWatcher ViewsWatcher = new FileSystemWatcher();
                    ViewsWatcher.Path = AppConfigUtil.Configuration["Frame:ViewsVirtualPath"];
                    ViewsWatcher.Changed += ViewsWatcher_Changed;
    
                    ViewsWatcher.IncludeSubdirectories = true;
                    ViewsWatcher.NotifyFilter =
                        NotifyFilters.Attributes | NotifyFilters.CreationTime | NotifyFilters.DirectoryName | NotifyFilters.FileName | NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.Security | NotifyFilters.Size;
                    ViewsWatcher.EnableRaisingEvents = true;
    
                    //系统启动时整个文件夹拷贝
                    DirectoryInfo FrameWorkViews = new DirectoryInfo(CloudUtil.GetContentPath() + "/Views");
                    DirectoryInfo ProjectViews = new DirectoryInfo(AppConfigUtil.Configuration["Frame:ViewsVirtualPath"]);
                    foreach (DirectoryInfo FDir in FrameWorkViews.GetDirectories())
                    {
                        foreach (DirectoryInfo PDir in ProjectViews.GetDirectories())
                        {
                            if (PDir.Name== FDir.Name)
                            {
                                FileUtil.DeleteDirectoryContent(FDir.FullName);
                            }
                        }
                    }
                    FileUtil.CopyDirectory(AppConfigUtil.Configuration["Frame:ViewsVirtualPath"],CloudUtil.GetContentPath() + "/Views", true);
                }
            }

    项目dll热更新

    监控Plugin文件夹,若有变调用IApplicationLifetime的StopApplication重启系统

     public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IConfiguration configuration, Microsoft.AspNetCore.Hosting.IApplicationLifetime applicationLifetime)
     {
          CloudUtil.SetAPP(applicationLifetime);
     }
    
    
     private static void _FileSystemWatcher_Changed(object sender, FileSystemEventArgs e)
     {
          CloudUtil.Restrat();
     }
    
     public static void Restrat()
     {
          APP.StopApplication();
     }
  • 相关阅读:
    英语语法基础知识总结名词
    英语语法基础知识代词
    idea破解第二部
    Linux(centos)系统下安装fastdfs安装部署步骤
    死磕Synchronized底层实现概论偏向锁轻量级锁重量级锁
    深入理解Mysql事务隔离级别与锁机制
    事务的传播机制
    ICCV2021 | TokenstoToken ViT:在ImageNet上从零训练Vision Transformer
    计算机视觉CV技术指南文章汇总
    资源分享 | PyTea:不用运行代码,静态分析pytorch模型的错误
  • 原文地址:https://www.cnblogs.com/yanpeng19940119/p/14493690.html
Copyright © 2020-2023  润新知