[转载]MVC 插件式开发 – yangwen1 – 博客园.
在开发一个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()); 注册自己的视图引擎
/// /// 虚拟路径提供者配置 /// public class VirtualPathConfig { /// /// 注册虚拟路径提供者以实现模块化拆分 /// 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 { /// /// 自定义的虚拟路径提供者。 /// public class GriffinVirtualPathProvider : VirtualPathProvider { private static readonly GriffinVirtualPathProvider Instance = new GriffinVirtualPathProvider(); private readonly List fileProviders = new List(); /// /// 初始化 GriffinVirtualPathProvider 类的新实例。 /// private GriffinVirtualPathProvider() { } /// /// 获得实例。 /// public static GriffinVirtualPathProvider Current { get { return Instance; } } /// /// 添加一个新的文件提供者。 /// ///文件提供者。 public void Add(IViewFileProvider fileProvider) { if (fileProvider == null) { throw new ArgumentNullException("fileProvider"); } this.fileProviders.Add(fileProvider); } /// /// 获取一个值,该值指示文件是否存在于虚拟文件系统中。 /// /// /// 如果该文件存在于虚拟文件系统中,则为 true;否则为 false。 /// ///虚拟文件的路径。 public override bool FileExists(string virtualPath) { foreach (var provider in this.fileProviders) { if (provider.FileExists(virtualPath)) { return true; } } return base.FileExists(virtualPath); } /// /// 基于指定的虚拟路径创建一个缓存依赖项。 /// ///主虚拟资源的路径。 ///一个路径数组,路径指向主要虚拟资源需要的其他资源。 ///虚拟资源被读取的 UTC 时间。 /// /// 指定虚拟资源的 对象。 /// 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); } /// /// 返回一个用于指定虚拟路径的缓存键。 /// ///虚拟资源的路径。 /// /// 所指定虚拟资源的缓存键。 /// 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); } /// /// 从虚拟文件系统中获取一个虚拟文件。 /// ///虚拟文件的路径。 /// /// 类的子代,该子代表示虚拟文件系统中的一个文件。 /// 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); } /// /// 返回指定虚拟路径的哈希值。 /// ///主虚拟资源的路径。 ///一个路径数组,所包含的路径指向主要虚拟资源需要的其他虚拟资源。 /// /// 指定虚拟路径的哈希值。 /// 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 { /// /// Locator which loads views using the project structure to enable runtime view edits. /// /// /// Works as long as you have used the structure which is described in the namespace documentation. /// public class PluginFileLocator : IViewFileLocator { private readonly string basePath; private IEnumerable allowedFileExtensions; /// /// Initializes a new instance of the class. /// public PluginFileLocator() { this.basePath = Path.GetFullPath(HostingEnvironment.MapPath("~") + @".."); } #region IViewFileLocator Members /// /// Get full path to a file /// ///Requested uri /// ~/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 /// /// Full disk path if found; otherwise null. /// 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; } /// /// Set extensions that are allowed to be scanned. /// ///File extensions without the dot. public void SetAllowedExtensions(IEnumerable fileExtensions) { this.allowedFileExtensions = fileExtensions; } /// /// determins if the found embedded file might be mapped and provided. /// ///Full path to the file /// true if the file is allowed; otherwise false. 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 } }
然后再获取缓存
/// /// 返回一个用于指定虚拟路径的缓存键。 /// ///虚拟资源的路径。 /// /// 所指定虚拟资源的缓存键。 /// 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); }
缓存没找到,从虚拟文件系统中获取一个虚拟文件
/// /// 从虚拟文件系统中获取一个虚拟文件。 /// ///虚拟文件的路径。 /// /// 类的子代,该子代表示虚拟文件系统中的一个文件。 /// 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/p/3898168.html帮助你跟好的理解。
成都卖身,有成都的朋友,可以推荐工作吗?
手机:18244293044
yangwensb@gmail.com