MVC 插件式开发

在开发一个OA系统是,我们可能遇到 A模块. B模块 .C模块,这也模块组成一个完整的系统,买给客服。
现在又有一个客服要我们做一个OA系统,唉我们发现,跟上一个OA系统差不多,但没有C模块。怎么办?

修改源码,系统简单还好,但是一系统复杂到一定程度,修改源码改这改这就像重写了!

怎么办,MVC插件式开发帮你解决问题,先看演示,再看代码。

CCAV.WebSite 是主站,引用 CCAV.Modules.Category
 CCAV.Modules.Category 就像当于一个模块,具体看演示。


通过主站可以访问到CCAV.Modules.Category 的控制器,如果 主站移除 对 CCAV.Modules.Category引用 将访问不到  CCAV.Modules.Category 你的控制器。
这样刚才的问题就解决了!

现在看一下主要代码。

 public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            VirtualPathConfig.Register();
            ViewEngines.Engines.Clear();
            ViewEngines.Engines.Add(new RazorViewEngineExpand());

            AreaRegistration.RegisterAllAreas();
            RouteConfig.RegisterRoutes(RouteTable.Routes);
        }
    }
VirtualPathConfig.Register();/ 注册虚拟路径提供者以实现模块化拆分
ViewEngines.Engines.Clear(); 移除全部视图引擎.....
ViewEngines.Engines.Add(new RazorViewEngineExpand()); 假如自己的视图引擎
  /// <summary>
    /// 虚拟路径提供者配置
    /// </summary>
    public class VirtualPathConfig
    {
        /// <summary>
        /// 注册虚拟路径提供者以实现模块化拆分
        /// </summary>
        public static void Register()
        {
            GriffinVirtualPathProvider.Current.Add(new StaticFileProvider(new PluginFileLocator()));
            GriffinVirtualPathProvider.Current.Add(new ViewFileProvider(new PluginFileLocator(), new ExternalViewFixer()));

            HostingEnvironment.RegisterVirtualPathProvider(GriffinVirtualPathProvider.Current);
        }
    }
   HostingEnvironment.RegisterVirtualPathProvider(GriffinVirtualPathProvider.Current);注册新的虚拟路径提供者:
StaticFileProvider  提供对图片、脚本、样式表等静态文件的访问
ViewFileProvider   视图文件提供
StaticFileProvider  ViewFileProvider  继承于 IViewFileProvider 看他们的内部实现
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Web.Caching;
using System.Web.Hosting;

namespace ItCast.Foundation.Hosting
{
    /// <summary>
    /// 自定义的虚拟路径提供者。
    /// </summary>
    public class GriffinVirtualPathProvider : VirtualPathProvider
    {
        private static readonly GriffinVirtualPathProvider Instance = new GriffinVirtualPathProvider();
        private readonly List<IViewFileProvider> fileProviders = new List<IViewFileProvider>();

        /// <summary>
        /// 初始化 GriffinVirtualPathProvider 类的新实例。
        /// </summary>
        private GriffinVirtualPathProvider()
        {
        }

        /// <summary>
        /// 获得实例。
        /// </summary>
        public static GriffinVirtualPathProvider Current
        {
            get
            {
                return Instance;
            }
        }

        /// <summary>
        /// 添加一个新的文件提供者。
        /// </summary>
        /// <param name="fileProvider">文件提供者。</param>
        public void Add(IViewFileProvider fileProvider)
        {
            if (fileProvider == null)
            {
                throw new ArgumentNullException("fileProvider");
            }

            this.fileProviders.Add(fileProvider);
        }

        /// <summary>
        /// 获取一个值,该值指示文件是否存在于虚拟文件系统中。
        /// </summary>
        /// <returns>
        /// 如果该文件存在于虚拟文件系统中,则为 true;否则为 false。
        /// </returns>
        /// <param name="virtualPath">虚拟文件的路径。</param>
        public override bool FileExists(string virtualPath)
        {
            foreach (var provider in this.fileProviders)
            {
                if (provider.FileExists(virtualPath))
                {
                    return true;
                }
            }

            return base.FileExists(virtualPath);
        }

        /// <summary>
        /// 基于指定的虚拟路径创建一个缓存依赖项。
        /// </summary>
        /// <param name="virtualPath">主虚拟资源的路径。</param>
        /// <param name="virtualPathDependencies">一个路径数组,路径指向主要虚拟资源需要的其他资源。</param>
        /// <param name="utcStart">虚拟资源被读取的 UTC 时间。</param>
        /// <returns>
        /// 指定虚拟资源的 <see cref="T:System.Web.Caching.CacheDependency"/> 对象。
        /// </returns>
        public override CacheDependency GetCacheDependency(
            string virtualPath,
            IEnumerable virtualPathDependencies,
            DateTime utcStart)
        {
            foreach (var provider in this.fileProviders)
            {
                var result = provider.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart);
                if (result is NoCache)
                {
                    return null;
                }

                if (result != null)
                {
                    return result;
                }
            }

            return base.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart);
        }

        /// <summary>
        /// 返回一个用于指定虚拟路径的缓存键。
        /// </summary>
        /// <param name="virtualPath">虚拟资源的路径。</param>
        /// <returns>
        /// 所指定虚拟资源的缓存键。
        /// </returns>
        public override string GetCacheKey(string virtualPath)
        {
            foreach (
                var result in
                    this.fileProviders.Select(provider => provider.GetCacheKey(virtualPath)).Where(result => result != null))
            {
                return result;
            }

            return base.GetCacheKey(virtualPath);
        }

        /// <summary>
        /// 从虚拟文件系统中获取一个虚拟文件。
        /// </summary>
        /// <param name="virtualPath">虚拟文件的路径。</param>
        /// <returns>
        /// <see cref="T:System.Web.Hosting.VirtualFile"/> 类的子代,该子代表示虚拟文件系统中的一个文件。
        /// </returns>
        public override VirtualFile GetFile(string virtualPath)
        {
            foreach (var provider in this.fileProviders)
            {
                var file = provider.GetFile(virtualPath);
                if (file != null)
                {
                    return file;
                }
            }

            return base.GetFile(virtualPath);
        }

        /// <summary>
        /// 返回指定虚拟路径的哈希值。
        /// </summary>
        /// <param name="virtualPath">主虚拟资源的路径。</param>
        /// <param name="virtualPathDependencies">一个路径数组,所包含的路径指向主要虚拟资源需要的其他虚拟资源。</param>
        /// <returns>
        /// 指定虚拟路径的哈希值。
        /// </returns>
        public override string GetFileHash(string virtualPath, IEnumerable virtualPathDependencies)
        {
            foreach (
                var result in
                    this.fileProviders.Select(provider => provider.GetFileHash(virtualPath, virtualPathDependencies)).Where(
                        result => result != null))
            {
                return result;
            }

            return base.GetFileHash(virtualPath, virtualPathDependencies);
        }
    }
}

一开始进入这个方法 FileExists 判断文件是否存在,春在这位true

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Hosting;

namespace ItCast.Foundation.Hosting
{
    /// <summary>
    /// Locator which loads views using the project structure to enable runtime view edits.
    /// </summary>
    /// <remarks>
    /// Works as long as you have used the structure which is described in the namespace documentation.
    /// </remarks>
    public class PluginFileLocator : IViewFileLocator
    {
        private readonly string basePath;
        private IEnumerable<string> allowedFileExtensions;

        /// <summary>
        /// Initializes a new instance of the <see cref="PluginFileLocator"/> class.
        /// </summary>
        public PluginFileLocator()
        {
            this.basePath = Path.GetFullPath(HostingEnvironment.MapPath("~") + @"..");
        }

        #region IViewFileLocator Members

        /// <summary>
        /// Get full path to a file
        /// </summary>
        /// <param name="uri">Requested uri</param>
        /// ~/Admin/Content/themes/Blog/Site.css
        /// ~/Admin/Scripts/Blog/BlogAjax.js
        /// ~/Admin/Views/Blog/Home/Index.cshtml
        /// ~/Content/themes/Blog/Site.css
        /// ~/Scripts/Blog/BlogAjax.js
        /// ~/Views/Blog/Home/Index.cshtml
        /// <returns>
        /// Full disk path if found; otherwise <c>null</c>.
        /// </returns>
        public string GetFullPath(string uri)
        {
            var pathConfigs = PluginPathConfig.GetConfigs();
            var fixedUri = uri;
            if (fixedUri.StartsWith("~"))
            {
                fixedUri = VirtualPathUtility.ToAbsolute(uri);
            }

            var path = string.Empty;
            foreach (var pattern in pathConfigs.Keys)
            {
                var regex = new Regex(pattern, RegexOptions.IgnoreCase);
                var match = regex.Match(fixedUri);
                if (match.Length > 0)
                {
                    path = Regex.Replace(fixedUri, pattern, pathConfigs[pattern], RegexOptions.IgnoreCase);
                    path = string.Format("{0}\\{1}", this.basePath, path.Replace(‘/‘, ‘\\‘));
                    break;
                }
            }

            if (!this.IsFileAllowed(uri))
            {
                return null;
            }

            if (File.Exists(path))
            {
                return path;
            }

            return null;
        }

        /// <summary>
        /// Set extensions that are allowed to be scanned.
        /// </summary>
        /// <param name="fileExtensions">File extensions without the dot.</param>
        public void SetAllowedExtensions(IEnumerable<string> fileExtensions)
        {
            this.allowedFileExtensions = fileExtensions;
        }

        /// <summary>
        /// determins if the found embedded file might be mapped and provided.
        /// </summary>
        /// <param name="fullPath">Full path to the file</param>
        /// <returns><c>true</c> if the file is allowed; otherwise <c>false</c>.</returns>
        protected virtual bool IsFileAllowed(string fullPath)
        {
            if (fullPath == null)
            {
                throw new ArgumentNullException("fullPath");
            }

            var extension = fullPath.Substring(fullPath.LastIndexOf(‘.‘) + 1);
            return this.allowedFileExtensions.Any(x => x == extension.ToLower());
        }

        #endregion
    }
}

然后再获取缓存

    /// <summary>
        /// 返回一个用于指定虚拟路径的缓存键。
        /// </summary>
        /// <param name="virtualPath">虚拟资源的路径。</param>
        /// <returns>
        /// 所指定虚拟资源的缓存键。
        /// </returns>
        public override string GetCacheKey(string virtualPath)
        {
            foreach (
                var result in
                    this.fileProviders.Select(provider => provider.GetCacheKey(virtualPath)).Where(result => result != null))
            {
                return result;
            }

            return base.GetCacheKey(virtualPath);
        }

缓存没找到,从虚拟文件系统中获取一个虚拟文件

  /// <summary>
        /// 从虚拟文件系统中获取一个虚拟文件。
        /// </summary>
        /// <param name="virtualPath">虚拟文件的路径。</param>
        /// <returns>
        /// <see cref="T:System.Web.Hosting.VirtualFile"/> 类的子代,该子代表示虚拟文件系统中的一个文件。
        /// </returns>
        public override VirtualFile GetFile(string virtualPath)
        {
            foreach (var provider in this.fileProviders)
            {
                var file = provider.GetFile(virtualPath);
                if (file != null)
                {
                    return file;
                }
            }

            return base.GetFile(virtualPath);
        }

就是这样一个流程..................................

资料:http://msdn.microsoft.com/zh-cn/library/system.web.hosting.virtualpathprovider(VS.80).aspx

源码:http://pan.baidu.com/s/1pJsgaIf

你可以看这篇文章:http://www.cnblogs.com/liek/ 帮助你跟好的理解。

成都卖身,有成都的朋友,可以推荐工作吗?
手机:18244293044
[email protected]
=======================================================

希望你可以从中获益  :)


MVC 插件式开发,布布扣,bubuko.com

时间: 2024-10-24 14:04:54

MVC 插件式开发的相关文章

MVC插件式开发平台

---恢复内容开始--- 经过DyOS.BraveOS1.0再到BraveOS2.0,系统现在已经开发了下载. 我们的目标是,网页版操作系统,可以在线安装更新软件,并提供二次开发平台,提供基础的逻辑和控件,我们将在后期公开开发文档,如果您不会html5,不会自己写js插件,那么这将是您的福音,因为,这些事我们会为你来更新完善!您只管用就行,哈哈. 我们的系统不支持IE这个老东西,支持谷歌内核所有浏览器. 由于官方网站即将发布,将随官方网站和二次开发文档一起发布,请持续关注www.braveos.

零基础ASP.NET Core MVC插件式开发

//services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);            services.AddMvc().ConfigureApplicationPartManager(apm =>            {                // 和主项目里面注册插件项目类似,这里注册主程序dll,主要是为了在vs里面直接运行调试,不需要发布到主项目用主项目来运行             

从零开始实现ASP.NET Core MVC的插件式开发(四) - 插件安装

标题:从零开始实现ASP.NET Core MVC的插件式开发(四) - 插件安装 作者:Lamond Lu 地址:https://www.cnblogs.com/lwqlun/p/11343141.html 源代码:https://github.com/lamondlu/DynamicPlugins 前情回顾 从零开始实现ASP.NET Core MVC的插件式开发(一) - 使用Application Part动态加载控制器和视图 从零开始实现ASP.NET Core MVC的插件式开发(二

从零开始实现ASP.NET Core MVC的插件式开发(六) - 如何加载插件引用

标题:从零开始实现ASP.NET Core MVC的插件式开发(六) - 如何加载插件引用. 作者:Lamond Lu 地址:https://www.cnblogs.com/lwqlun/p/11717254.html 源代码:https://github.com/lamondlu/DynamicPlugins 前景回顾 从零开始实现ASP.NET Core MVC的插件式开发(一) - 使用Application Part动态加载控制器和视图 从零开始实现ASP.NET Core MVC的插件

从零开始实现ASP.NET Core MVC的插件式开发(一) - 使用ApplicationPart动态加载控制器和视图

标题:从零开始实现ASP.NET Core MVC的插件式开发(一) - 使用Application Part动态加载控制器和视图作者:Lamond Lu地址:https://www.cnblogs.com/lwqlun/p/11137788.html源代码:https://github.com/lamondlu/Mystique 前言# 如果你使用过一些开源CMS的话,肯定会用过其中的的插件化功能,用户可以通过启用或者上传插件包的方式动态添加一些功能,那么在ASP.NET Core MVC中如

从零开始实现ASP.NET Core MVC的插件式开发(五) - 插件的删除和升级

标题:从零开始实现ASP.NET Core MVC的插件式开发(五) - 使用AssemblyLoadContext实现插件的升级和删除作者:Lamond Lu地址:https://www.cnblogs.com/lwqlun/p/11395828.html源代码:https://github.com/lamondlu/Mystique 前景回顾: 从零开始实现ASP.NET Core MVC的插件式开发(一) - 使用Application Part动态加载控制器和视图 从零开始实现ASP.N

也来学学插件式开发

上一家公司有用到插件式开发来做一个工具箱,类似于QQ电脑管家,有很多工具列表,点一下工具下载后就可以开始使用了.可惜在那家公司待的时候有点短,没有好好研究一下.现在有空,自己在网上找了些资料,也来试试. 主要思路:公开一个插件接口,如果.DLL或.EXE的代码中有继承这个接口就将其示为插件,并将这些插件放在同一目录.运行程序的时候扫描目录并通过反射判断.DLL或.EXE中是否存在该接口,若存在,则当作插件加载进来. 我们来做一个示例看看.例子也是在园子里找的,自己改了一下,详见:http://w

Android应用插件式开发解决方法

Android应用插件式开发解决方法 一.现实需求描述 一般的,一个Android应用在开发到了一定阶段以后,功能模块将会越来越多,APK安装包也越来越大,用户在使用过程中也没有办法选择性的加载自己需要的功能模块.此时可能就需要考虑如何分拆整个应用了. 二.解决方案提出 一般有两种方式,一种是将应用按照功能分拆成多个应用,用户需要哪个就下载哪个,都需要就都下载.应用之间,可以在代码层面做一定的关联,以共享部分信息.另一种方式,类似于其他平台插件的方式,用户可以在主应用中可以选择性的下载需要的插件

基于AppDomain的&quot;插件式&quot;开发

很多时候,我们都想使用(开发)USB式(热插拔)的应用,例如,开发一个WinForm应用,并且这个WinForm应用能允许开发人员定制扩展插件,又例如,我们可能维护着一个WinService管理系统,这个WinService系统管理的形形色色各种各样的服务,这些服务也是各个"插件式"的类库,例如: public interface IJob { void Run(DateTime time); } public class CollectUserInfo : IJob { public