[转载]ASP.NET MVC 插件式开发 - yangwen1 - 博客园

[转载]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

赞(0) 打赏
分享到: 更多 (0)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏