首页 > 代码库 > MVC 插件式开发

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
yangwensb@gmail.com
=======================================================

希望你可以从中获益  :)