10.MVC插件系统(控制器和视图)
1:重写控制器
2:重写视图引擎
注意我们做的插件就是拿来给主站用,从而提高开发效率,
我们的每个子站都是通过一个类来重写对应的方法来给主站引用,从而达到引入插件的功能,
注意.我们在主站中使用从站插件时一定要把整个从站的Views文件夹复制到主站,
重写操作: 1:控制器defulatControllerFactoty 下的 GetControllerType
2:视图 视图引擎:RazorViewEngine 下的FindView或则ParailView
重写原因:因为我们使用的插件需要导入到主站,但是我们的dll文件只会默认的加载到当前主站的bin目录下,所以主站将会找不到我们插入的的dll文件,所以我们需要重写指定的方法(如果是视图那么我们就需要重写视图引擎如果不是返回视图那么我们就需要重写),让主站加载到插件的dll文件
例子:
重写defulatControllerFactoty ,和 RazorViewEnginee 来实现MVC的插件式开发
2.1、将控制器提取到插件项目中实现步骤
2.1.1、定义一个类继承DefaultControllerFactory ,重写里面的方法GetControllerType
protected override Type GetControllerType(System.Web.Routing.RequestContext requestContext, string controllerName)
例子:
public class PluginControllerFactory : DefaultControllerFactory
{
requestContext是上下文对象 controllerName是控制器名称
protected override Type GetControllerType(System.Web.Routing.RequestContext requestContext, string controllerName)
{
Type controllerType = null;
//1.0 当浏览器发出一个url请求的时候,在管道事件第7个上会触发控制器创建动作,一定触发工厂中GetControllerType方法
//所以,在此处就先从网站主站的Plugins文件夹 通过反射创建一个当前请求控制器的 Type ,如果没有找到,则一定会返回null
//那么此时就调用base.GetControllerType(requestContext, controllerName); 从当前网站的bin目录下查找
//1.0 获取当前网站的运行目录
string phyPath = AppDomain.CurrentDomain.BaseDirectory; 程序域:根据程序域获取当前主站的文件目录的物理路径
//2.0 获取当前网站的插件目录
string plugsPahyPath = phyPath + "Plugins";
//3.0 将传入的controllerName 加上固定后缀"Controller"
string pullName = controllerName + "Controller";
//4.0 通过程序集中的GetType()方法获取当前控制器的Type对象
//4.0.1 获取Plugins 下面的所有后缀名为 .dll的程序集路径
string[] dllfilePhyPaths = System.IO.Directory.GetFiles(plugsPahyPath, "*.dll", System.IO.SearchOption.AllDirectories);
//5.0 遍历dll的物理路径将dll加载的Assembly 中
if (dllfilePhyPaths != null && dllfilePhyPaths.Length > 0)
{
foreach (var dllfilephyPath in dllfilePhyPaths)
{
//5.0.1 根据dll的物理路径将dll加载到dllass中
Assembly dllass = Assembly.LoadFile(dllfilephyPath);
controllerType = dllass.GetType("MVC.Plugs.Controllers." + pullName);
if (controllerType != null)
{
break;
}
}
}
if (controllerType != null)
{
return controllerType;
}
return base.GetControllerType(requestContext, controllerName);
}
}
2.1.2、在MVC主网站跟目录下定义一个 Plugins文件夹,将插件中生成的dll拷贝到其中
2.1.3、在mvc主网站的Global.asax中的 Application_Start() 方法中加入如下代码:
将MVC控制器类的创建行为动作交给自己定义好的PluginControllerFactory 工厂
ControllerBuilder.Current.SetControllerFactory(new PluginControllerFactory());
2.2、将视图提取到插件项目中实现步骤
1、
public class PluginsRazorViewEngine : RazorViewEngine
{
/// <summary>
/// 自己定义 视图引擎查找视图的路径
/// </summary>
private string[] ViewLocationFormats ={
"~/Plugins/Order/Views/{1}/{0}.cshtml",
"~/Plugins/Order/Views/Shared/{1}/{0}.cshtml",
"~/Views/{1}/{0}.cshtml",
"~/Views/Shared/{1}/{0}.cshtml",
};
public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
{
//1.0 将父类RazorViewEngine中的ViewLocationFormats设置成本类定义的路径
base.ViewLocationFormats = this.ViewLocationFormats;
//2.0 重写视图引擎将 视图编译成前台页面类的方法
RazorBuildProvider.CodeGenerationStarted += RazorBuildProvider_CodeGenerationStarted;
return base.FindView(controllerContext, viewName, masterName, useCache);
}
void RazorBuildProvider_CodeGenerationStarted(object sender, EventArgs e)
{
RazorBuildProvider provider = sender as RazorBuildProvider;
//将哪个程序集编译到当前视图引用中
//1.0 获取当前网站的运行目录
string phyPath = AppDomain.CurrentDomain.BaseDirectory;
//2.0 获取当前网站的插件目录
string plugsPahyPath = phyPath + "Plugins";
//4.0 通过程序集中的GetType()方法获取当前控制器的Type对象
//4.0.1 获取Plugins 下面的所有后缀名为 .dll的程序集路径
string[] dllfilePhyPaths = System.IO.Directory.GetFiles(plugsPahyPath, "MVC.Plugs.dll", System.IO.SearchOption.AllDirectories);
string mvcplugsdllPath = dllfilePhyPaths[0];
Assembly ass = Assembly.LoadFile(mvcplugsdllPath);
//5.0 将ass 添加为视图前台页面类的引用程序集
provider.AssemblyBuilder.AddAssemblyReference(ass);
}
2、在mvc主网站的Global.asax中的 Application_Start() 方法中加入如下代码:
//移除当前MVC主站点中的所有视图引擎
ViewEngines.Engines.Clear();
//将自己定义好的引擎添加到MVC中
ViewEngines.Engines.Add(new PluginsRazorViewEngine());
浙公网安备 33010602011771号