您的位置:首页 > 编程语言 > ASP

如何用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>

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: