Asp.net Vnext 模块化实现
概述
本文已经同步到《Asp.net Vnext 系列教程 》中]
在程序中实现模块化可以加快开发效率,通过替换模块实现升级.
架构
vnext 没有 Virtualpathprovider,本文通过IFileProvider实现模块

ModularVNext.Startup 启动类
public class Startup
{
private IFileProvider _modulesFileProvider;
private readonly string ApplicationBasePath;
private readonly IAssemblyLoadContextAccessor _assemblyLoadContextAccessor;
private readonly IAssemblyLoaderContainer _assemblyLoaderContainer;
public Startup(IHostingEnvironment hostingEnvironment,
IApplicationEnvironment applicationEnvironment,
IAssemblyLoaderContainer assemblyLoaderContainer,
IAssemblyLoadContextAccessor assemblyLoadContextAccessor)
{
//程序集加载上下文访问
_assemblyLoadContextAccessor = assemblyLoadContextAccessor;
//程序集加载容器
_assemblyLoaderContainer = assemblyLoaderContainer;
//程序基本路径
ApplicationBasePath = applicationEnvironment.ApplicationBasePath;
Configuration = new Configuration()
.AddJsonFile("config.json")
.AddEnvironmentVariables();
} public IConfiguration Configuration { get; set; } public void ConfigureServices(IServiceCollection services)
{
var basePaths = Configuration.Get("additionalFileProviderBasePaths")?.Split(';') ?? new string[] { };
var modulesPath = Path.Combine(ApplicationBasePath.Substring(,ApplicationBasePath.IndexOf("src")), Configuration.Get("moduleLoadPath")); var moduleAssemblies = LoadAssembliesFrom(modulesPath, _assemblyLoaderContainer, _assemblyLoadContextAccessor); _modulesFileProvider = GetModulesFileProvider(basePaths, moduleAssemblies); services.AddInstance(Configuration); services.AddMvc(); services.Configure<RazorViewEngineOptions>(o =>
{
o.FileProvider = _modulesFileProvider;
}); services.AddInstance(new ModuleAssemblyLocator(moduleAssemblies));
services.AddTransient<DefaultAssemblyProvider>();
services.AddTransient<IAssemblyProvider, ModuleAwareAssemblyProvider>();
} public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerfactory)
{
loggerfactory.AddConsole(); if (string.Equals(env.EnvironmentName, "Development", StringComparison.OrdinalIgnoreCase))
{
app.UseBrowserLink();
app.UseErrorPage(ErrorPageOptions.ShowAll);
}
else
{
app.UseErrorHandler("/Home/Error");
} app.UseStaticFiles(new StaticFileOptions
{
FileProvider = _modulesFileProvider
}); app.UseMvc(routes =>
{
routes.MapRoute(
name: "areaRoute",
template: "{area:exists}/{controller}/{action}",
defaults: new { controller = "Home", action = "Index" }
);
routes.MapRoute(
name: "default",
template: "{controller}/{action}/{id?}",
defaults: new { controller = "Home", action = "Index" });
});
} private List<Assembly> LoadAssembliesFrom(string modulesDirectory,
IAssemblyLoaderContainer assemblyLoaderContainer,
IAssemblyLoadContextAccessor loadContextAccessor)
{
var assemblies = new List<Assembly>();
var loadContext = _assemblyLoadContextAccessor.GetLoadContext(typeof(Startup).GetTypeInfo().Assembly);
using (assemblyLoaderContainer.AddLoader(new DirectoryLoader(modulesDirectory, loadContext)))
{ foreach (var modulePath in Directory.EnumerateFiles(@"C:\Users\Administrator\Documents\Visual Studio 2015\Projects1\ModularVNext\artifacts\bin\Module1\Debug\dnx451", "*.dll"))
{
var name = Path.GetFileNameWithoutExtension(modulePath);
assemblies.Add(loadContext.Load(name));
}
}
return assemblies;
} private IFileProvider GetModulesFileProvider(string[] basePaths, List<Assembly> moduleAssemblies)
{ var redirectedFileProviders = basePaths
.Select(path => Path.IsPathRooted(path) ? path : Path.Combine(ApplicationBasePath, path))
.Select(root => new PhysicalFileProvider(root)).ToList(); var resourceFileProviders = moduleAssemblies.Select(a => new SafeEmbeddedFileProvider(a)).ToList(); var redirectedFileProviders1= redirectedFileProviders.Select(x => x as IFileProvider);
var resourceFileProviders1= resourceFileProviders.Select(x => x as IFileProvider);
var co= redirectedFileProviders1.Concat<IFileProvider>(resourceFileProviders1).ToList(); IFileProvider rootProvider = new PhysicalFileProvider(ApplicationBasePath); co.Add(rootProvider);
return new CompositeFileProvider(co); } }
ConfigureServices 方法主要是获取模块程序集和模块程序提供者
var moduleAssemblies = LoadAssembliesFrom(modulesPath, _assemblyLoaderContainer, _assemblyLoadContextAccessor);
通过LoadAssembliesFrom方法获取模块程序集
参数:
modulesPath 模块的路径

也就是 Module1的程序集路径

选择该选项,然后编译就可以输出程序集了

在根目录下\artifacts\bin\Module1\Debug\会产生两个程序集分别是 dnx451 和 dnxcore50 ,这里我选择的是dnx451
集体实现
private List<Assembly> LoadAssembliesFrom(string modulesDirectory,
IAssemblyLoaderContainer assemblyLoaderContainer,
IAssemblyLoadContextAccessor loadContextAccessor)
{
var assemblies = new List<Assembly>(); //程序集加载上下文
var loadContext = _assemblyLoadContextAccessor.GetLoadContext(typeof(Startup).GetTypeInfo().Assembly); //添加程序集加载
using (assemblyLoaderContainer.AddLoader(new DirectoryLoader(modulesDirectory, loadContext)))
{ //找出文件夹下的程序集,我这里写的是硬编码
foreach (var modulePath in Directory.EnumerateFiles(@"C:\Users\Administrator\Documents\Visual Studio 2015\Projects1\ModularVNext\artifacts\bin\Module1\Debug\dnx451", "*.dll"))
{
var name = Path.GetFileNameWithoutExtension(modulePath);
//加载程序集
assemblies.Add(loadContext.Load(name));
}
}
return assemblies;
}
返回程序集在条用_modulesFileProvider 获取文件提供者然后把获取到的文件提供者设置到RazorViewEngineOptions
services.Configure<RazorViewEngineOptions>(o =>
{
o.FileProvider = _modulesFileProvider;
});
ModularVNext.Infrastructure.CompositeFileProvider这是实现IFileProvider的类
public class CompositeFileProvider : IFileProvider
{
//提供者目录
private List<IFileProvider> _fileProviders;
//触发器
private readonly Dictionary<string, TestFileTrigger> _fileTriggers =
new Dictionary<string, TestFileTrigger>(StringComparer.Ordinal);
public CompositeFileProvider(IEnumerable<IFileProvider> fileProviders)
{
_fileProviders = fileProviders.ToList();
} public IDirectoryContents GetDirectoryContents(string subpath)
{
foreach (var fileProvider in _fileProviders)
{
//更具subpat获取目录
var contents = fileProvider.GetDirectoryContents(subpath);
if (contents != null && contents.Exists)
{
return contents;
}
}
return new NotFoundDirectoryContents();
} public IFileInfo GetFileInfo(string subpath)
{
foreach (var fileProvider in _fileProviders)
{//更具subpat获取文件信息
var fileInfo = fileProvider.GetFileInfo(subpath);
if (fileInfo != null && fileInfo.Exists)
{
return fileInfo;
}
}
return new NotFoundFileInfo(subpath);
} public IExpirationTrigger Watch(string filter)
{ //触发器
TestFileTrigger trigger; trigger = new TestFileTrigger(); return trigger; }
} internal class TestFileTrigger : IExpirationTrigger
{
public bool ActiveExpirationCallbacks
{
get { return false; }
}
private CancellationToken Token { get; set; }
public bool IsExpired
{
get { return false; }
} public IDisposable RegisterExpirationCallback(Action<object> callback, object state)
{
return null;
}
}

没有对Module1引用
运行程序

http://pan.baidu.com/s/1eQdakoy 下载地址
Asp.net Vnext 模块化实现的更多相关文章
- [译]Introducing ASP.NET vNext and MVC 6
原文:http://www.infoq.com/news/2014/05/ASP.NET-vNext?utm_source=tuicool Part of the ASP.NET vNext init ...
- 微软下一代云环境Web开发框架ASP.NET vNext预览
微软在2014年5月12日的TechEd大会上宣布将会公布下一代ASP.NET框架ASP.NET vNext的预览.此次公布的ASP.NET框架与曾经相比发生了根本性的变化,凸显了微软"云优 ...
- ASP.NET vNext or .NET vNext?
ASP.NET vNext or .NET vNext? 从概念和基础开始 vNext在曝光以来绝大多数以ASP.NET vNext这样的的字眼出现,为什么这边会提及.NET vNext?原因是我认为 ...
- ASP.NET vNext (一)- 基本概念和环境配置
ASP.NET vNext (一)- 基本概念和环境配置 转发:微软MVP 卢建晖 的文章,希望对大家有帮助. 编者语:时代在变,在csdn开博一年就发了那么的两篇文章,无论是什么原因都觉得有愧了.但 ...
- Asp.net vNext 学习1
Asp.net vNext 学习之路(一) 概述 asp.net vNext 也叫 asp.net 5.0,意思是微软推出的下一个版本的asp.net.可以说是微软对asp.net的一个比较重大的重新 ...
- Introducing ASP.NET vNext and MVC 6
[译]Introducing ASP.NET vNext and MVC 6 原文:http://www.infoq.com/news/2014/05/ASP.NET-vNext?utm_source ...
- ASP.NET vNext:微软下一代云环境Web开发框架
作者 郭蕾 发布于 2014年5月16日 在5月12日的TechED大会上,微软首次向外界介绍了下一代ASP.NET框架——ASP.NET vNext.ASP.NET vNext专门针对云环境和服 ...
- Asp.net vNext 学习之路(一)
概述 asp.net vNext 也叫 asp.net 5.0,意思是微软推出的下一个版本的asp.net.可以说是微软对asp.net的一个比较重大的重新设计, asp.net vNext是一 个比 ...
- ASP.NET vNext 微笔记
关心 ASP.NET vNext 的人可能已经读过相关文章,例如:ASP.NET vNext @ 2014.那么,你可能已经知道,ASP.NET vNext 摆脱了 System.Web.DLL,把 ...
随机推荐
- 企业级镜像管理系统Harbor
Harbor简介 在说harbor之前,我们首先说一说直接使用docker registry的一些缺陷: 缺少认证机制,任何人都可以随意拉取及上传镜像,安全性缺失 缺乏镜像清理机制,镜像可以push却 ...
- Oracle 中常用数据字典大总结
原文出处:小宝马的爸爸 - 梦想的家园 前面呢,也断断续续的介绍了一些诸如 Sql*Plus 等等关于 Oracle 的基本的内容, 对于 Oracle 这样的大型数据库呢,自身的运行和维护也是个不得 ...
- Vue.js学习笔记(一)
其它前端主流框架可以做的事,Vue.js几乎都可以做, nuxt框架:可以实现vue的服务器端渲染, weex:使用vue语法编写原生app. 基础内容 基础语法 MVVM设计模式 前端组件化 vue ...
- presto架构和原理
Presto 是 Facebook 推出的一个基于Java开发的大数据分布式 SQL 查询引擎,可对从数 G 到数 P 的大数据进行交互式的查询,查询的速度达到商业数据仓库的级别,据称该引擎的性能是 ...
- soj1010. Zipper
1010. Zipper Constraints Time Limit: 1 secs, Memory Limit: 32 MB Description Given three strings, yo ...
- Windows上安装QT4后更改MinGW的路径
在windows上安装使用MinGW的QT4时,并不会一起安装MinGW. 在安装过程中,会让你指定已经安装的MinGW的路径. 当你使用QT4时,将使用你指定的MinGW的路径下的g++来编译构建程 ...
- springboot中使用Scheduled定时任务
一:在程序入口类中添加注解@EnableScheduling @SpringBootApplication @EnableScheduling public class DemoApplication ...
- mac nginx 安装及PHP配置
安装nginx 1.安装brew命令 ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/mas ...
- 【leetcode 简单】 第八十七题 两整数之和
不使用运算符 + 和-,计算两整数a .b之和. 示例: 若 a = 1 ,b = 2,返回 3. class Solution: def getSum(self, a, b): "&quo ...
- 添加 MySql 服务、Tomcat服务到windows服务中
添加 MySql 服务到windows服务中: cmd --> F:\MySql\MySqlServer5.1\bin\mysqld --install 这样用默认的 MySQL 为名称添加一个 ...