如何用MEF实现Asp.Net MVC框架
2013-07-10 15:42
387 查看
目的是实现多个Controller类,View在不同的dll里, 供一个大框架调用。 原理:1.用MEF实现各个Controller类的dll的导出和导入。2.用[PartCreationPolicy(CreationPolicy.NonShared)]标记来实现每个Controller在Export时重新创建实例3.继承DefaultControllerFactory来创建我们自定义的ControllerFactory。4.用ControllerBuilder.Current.SetControllerFactory 调用我们创建的ControllerFactory类5.继承RazorViewEngine, 实现我们自定义的ViewEngine。6.用ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(我们实现的自定义ViewEngine);
7.继承VirtualPathProvider和VirtualFile实现我们自定义的VirtualPath, 来查找各个子模块的资源(View)
8.用System.Web.Hosting.HostingEnvironment.RegisterVirtualPathProvider(我们自定义的VirtualPathProvider);
9.子模块中的改变,1:每个View的属性设置为Embedded Resource, 每个Controller类有Export和PartCreationPolicy属性。
集成遇到的问题
1. 修改Controller类:继承IPACSModule,添加[PartCreationPolicy(CreationPolicy.NonShared)]标签[PartCreationPolicy(CreationPolicy.NonShared)]public class PatientController : Controller,IPACSModule2. 修改View的属性Build Action为Embedder Resource 3. 修改XXXX.Cshtml, 添加@inherits System.Web.Mvc.WebViewPage, 如果Cshtml中有@model, 如:@model IEnumerable<OrderViewModel>改为@using System.Web.WebPages; @using System.Web.Mvc; @using System.Web.Mvc.Ajax; @using System.Web.Mvc.Html; @using System.Web.Routing; @inherits System.Web.Mvc.WebViewPage<IEnumerable<OrderViewModel>>@using (Ajax.BeginForm("Submit", new AjaxOptions { UpdateTargetId = "main" })){}
具体代码:
1.框架层的实现:
using System;using System.Collections.Generic;using System.ComponentModel.Composition;using System.ComponentModel.Composition.Hosting;using System.IO;using System.Linq;using System.Reflection;using System.Web;using System.Web.Caching;using System.Web.Hosting;using System.Web.Mvc;using System.Web.WebPages;using AddIn.Interface;using System.Globalization;using System.ComponentModel.Composition.Primitives; namespace Common{ public class ExtensionHelper { [ImportMany(AllowRecomposition = true)] public IEnumerable<IPACSModule> PACSModules { get; set; } public CompositionContainer _container; public void Initialize() { AggregateCatalog catalog = new AggregateCatalog(); catalog.Catalogs.Add(new AggregateCatalog( new DirectoryCatalog(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin")), new AssemblyCatalog(typeof(Controller).Assembly), new TypeCatalog(typeof(IPACSModule)) )); _container = new CompositionContainer(catalog); try { _container.ComposeParts(this); } catch (CompositionException ex) { throw new SystemException(ex.Message, ex); } //Set Custom Controller ControllerBuilder.Current.SetControllerFactory(new CustomControllerFactory()); //Set Custom ViewEngine ViewEngines.Engines.Clear(); ViewEngines.Engines.Add(new CustomViewEngine()); //Register a virtual path provider System.Web.Hosting.HostingEnvironment.RegisterVirtualPathProvider(new CustomVirtualPathProvider()); } } public class CustomControllerFactory : DefaultControllerFactory { protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType) { //{call AddIn controller var export = MvcApplication._extHelper._container.GetExports<IPACSModule>() .Where(e => e.Value.GetType().Equals(controllerType)) .FirstOrDefault(); if (null != export) { return export.Value as Controller; } else { return base.GetControllerInstance(requestContext, controllerType); } //end AddIn controller} } public override void ReleaseController(IController controller) { IDisposable disposable = controller as IDisposable; if (disposable != null) { disposable.Dispose(); } //base.ReleaseController(controller); } } public class CustomViewEngine : RazorViewEngine { public CustomViewEngine() { base.AreaViewLocationFormats = new string[] { "~/Areas/{2}/Views/{1}/{0}.cshtml", "~/Areas/{2}/Views/Shared/{0}.cshtml"}; base.AreaMasterLocationFormats = new string[] { "~/Areas/{2}/Views/{1}/{0}.cshtml", "~/Areas/{2}/Views/Shared/{0}.cshtml" }; base.AreaPartialViewLocationFormats = new string[] { "~/Areas/{2}/Views/{1}/{0}.cshtml", "~/Areas/{2}/Views/Shared/{0}.cshtml" }; base.ViewLocationFormats = new string[] { "~/Views/{1}/{0}.cshtml", "~/Views/Shared/{0}.cshtml", "~/PACSModule/Views/{1}/{0}.cshtml", "~/PACSModule/Views/Shared/{0}.cshtml"}; base.MasterLocationFormats = new string[] { "~/Views/{1}/{0}.cshtml", "~/Views/Shared/{0}.cshtml", "~/PACSModule/Views/{1}/{0}.cshtml", "~/PACSModule/Views/Shared/{0}.cshtml", "~/PACSModule/Views/{0}.cshtml"}; base.PartialViewLocationFormats = new string[] { "~/Views/{1}/{0}.cshtml", "~/Views/Shared/{0}.cshtml", "~/PACSModule/Views/{1}/{0}.cshtml", "~/PACSModule/Views/Shared/{0}.cshtml", "~/PACSModule/Views/{0}.cshtml"}; base.FileExtensions = new string[] { "cshtml"}; } protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath) { var dllName = controllerContext.Controller.GetType().Module.Name; return base.CreatePartialView(controllerContext, partialPath.Replace("PACSModule", dllName)); } protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath) { var dllName = controllerContext.Controller.GetType().Module.Name; RazorView razorView = new RazorView(controllerContext, viewPath.Replace("PACSModule", dllName), masterPath, false, base.FileExtensions, base.ViewPageActivator); return razorView; } protected override bool FileExists(ControllerContext controllerContext, string virtualPath) { var dllName = controllerContext.Controller.GetType().Module.Name; try { return base.FileExists(controllerContext, virtualPath.Replace("PACSModule", dllName)); } catch (System.Exception ex) { return false; } } } public class CustomView : RazorView { public CustomView(ControllerContext controllerContext, string viewPath, string layoutPath, bool runViewStartPages, IEnumerable<string> viewStartFileExtensions, IViewPageActivator viewPageActivator) : base(controllerContext, viewPath, layoutPath, runViewStartPages, viewStartFileExtensions, viewPageActivator) { } protected override void RenderView(ViewContext viewContext, TextWriter writer, object instance)
{ if (writer == null) { throw new ArgumentNullException("writer"); } WebViewPage layoutPath = instance as WebViewPage; if (layoutPath == null) { throw new InvalidOperationException("WebViewPage is null."); } layoutPath.VirtualPath = this.ViewPath; layoutPath.ViewContext = viewContext; layoutPath.ViewData = viewContext.ViewData; layoutPath.InitHelpers(); WebPageRenderingBase viewStartPage = null; if (this.RunViewStartPages) { try { viewStartPage = StartPage.GetStartPage(layoutPath, "_ViewStart", new string[] { "cshtml" }); } catch { viewStartPage = GetStartPage(layoutPath, "~/Views/_ViewStart.cshtml"); } } WebPageContext pageContext = new WebPageContext(null, null, null); layoutPath.ExecutePageHierarchy(pageContext, writer, viewStartPage); } private static StartPage GetStartPage(WebViewPage childPage, string startPagePath) { StartPage startPage = null; startPage = childPage.VirtualPathFactory.CreateInstance(startPagePath) as StartPage; startPage.VirtualPath = startPagePath; startPage.ChildPage = childPage; startPage.VirtualPathFactory = childPage.VirtualPathFactory; return startPage; }
} public class CustomVirtualPathProvider : VirtualPathProvider { private bool IsAppResourcePath(string virtualPath) { String checkPath = VirtualPathUtility.ToAppRelative(virtualPath); return checkPath.StartsWith("~/xxx", StringComparison.InvariantCultureIgnoreCase); } public override bool FileExists(string virtualPath) { return (IsAppResourcePath(virtualPath) || base.FileExists(virtualPath)); } public override VirtualFile GetFile(string virtualPath) { if (IsAppResourcePath(virtualPath)) { return new CustomVirtualFile(virtualPath); } else { return base.GetFile(virtualPath); } } public override System.Web.Caching.CacheDependency GetCacheDependency(string virtualPath, System.Collections.IEnumerable virtualPathDependencies, DateTime utcStart) { if (IsAppResourcePath(virtualPath)) { string[] parts = virtualPath.Split('/'); string assemblyName = parts[1]; Assembly asm = Assembly.Load(assemblyName.Replace(".DLL", "").Replace(".dll", "")); return new CacheDependency(asm.Location); } else { return base.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart); } } } public class CustomVirtualFile : VirtualFile { private string _virtualPath = ""; public CustomVirtualFile(string virtualPath) : base(virtualPath) { _virtualPath = VirtualPathUtility.ToAppRelative(virtualPath); } public override System.IO.Stream Open() { string[] parts = _virtualPath.Split('/'); string assemblyName = parts[1]; string resourceName = assemblyName.Replace(".DLL", "").Replace(".dll", "") + "." + parts[2] + "." + parts[3] + "." + parts[4]; //"UIH.PACS.Workstation.AddIn.Demo."+"Views." + "Controller." + "Action.cshtml" assemblyName = Path.Combine(HttpRuntime.BinDirectory, assemblyName); System.Reflection.Assembly assembly = System.Reflection.Assembly.LoadFile(assemblyName); if (null != assembly) { Stream resourceStream = assembly.GetManifestResourceStream(resourceName); return resourceStream; } return null; } }}
2.IPACSModule就是空接口, 用来各个子模块的controller的Export
[InheritedExport(typeof(IPACSModule))] public interface IPACSModule { }
3.子模块的Controller使用
[PartCreationPolicy(CreationPolicy.NonShared)] public class TestController : Controller, IPACSModule { // // GET: /Test/ public ActionResult Index() { return View(); } }
4. 子模块的View的使用
@inherits System.Web.Mvc.WebViewPage @{ ViewBag.Title = "Demo/Test/Index.cshtml";} <div class="content-wrapper"> This is Demo's index view for Test</div>
相关文章推荐
- 如何用MEF实现Asp.Net MVC框架
- ASP.NET MVC 如何实现头压缩
- ASP.NET WebForm Form表单如何实现MVC那种“自动装配”
- 【无私分享:从入门到精通ASP.NET MVC】从0开始,一起搭框架、做项目(5.5) 登录功能的实现,完善登录功能
- 扩展ASP.NET MVC三层框架并使用StructureMap实现依赖注入2-Repository层的实现
- ASP.NET MVC:如何实现一个自己的ModelBinder?
- 如何实现IEnumerable<T>和IEnumerator接口,一个ASP.NET MVC日志模型的实现
- ASP.NET MVC框架下使用MVVM模式 knockoutjs的实现原理
- 【搭建Spring.net+EF+Asp.net MVC框架】---(2)Demo实现
- 如何提高码农产量,基于ASP.NET MVC的敏捷开发框架开发随笔一
- asp.net mvc当出现错误时如何实现友好错误提示
- 如何在asp.net mvc框架及django框架下面避免CSRF
- 如何让你的ASP.NET MVC项目实现AJAX
- ASP.NET MVC如何实现自定义验证(服务端验证+客户端验证)
- 学习ASP.NET MVC5框架揭秘笔记-ASP.NET MVC是如何运行的(五)
- 如何在ASP.NET Core应用中实现与第三方IoC/DI框架的整合?
- 如何提高码农产量,基于ASP.NET MVC的敏捷开发框架开发随笔一
- ASP.NET MVC如何实现自定义验证(服务端验证+客户端验证)
- 关于ASP.NET MVC框架的代码提示汉化实现方法
- 搭建你的Spring.Net+Nhibernate+Asp.Net Mvc 框架 (三)实现数据库接口层和业务逻辑层(转)