概述


本文已经同步到《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 模块化实现的更多相关文章

  1. [译]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 ...

  2. 微软下一代云环境Web开发框架ASP.NET vNext预览

    微软在2014年5月12日的TechEd大会上宣布将会公布下一代ASP.NET框架ASP.NET vNext的预览.此次公布的ASP.NET框架与曾经相比发生了根本性的变化,凸显了微软"云优 ...

  3. ASP.NET vNext or .NET vNext?

    ASP.NET vNext or .NET vNext? 从概念和基础开始 vNext在曝光以来绝大多数以ASP.NET vNext这样的的字眼出现,为什么这边会提及.NET vNext?原因是我认为 ...

  4. ASP.NET vNext (一)- 基本概念和环境配置

    ASP.NET vNext (一)- 基本概念和环境配置 转发:微软MVP 卢建晖 的文章,希望对大家有帮助. 编者语:时代在变,在csdn开博一年就发了那么的两篇文章,无论是什么原因都觉得有愧了.但 ...

  5. Asp.net vNext 学习1

    Asp.net vNext 学习之路(一) 概述 asp.net vNext 也叫 asp.net 5.0,意思是微软推出的下一个版本的asp.net.可以说是微软对asp.net的一个比较重大的重新 ...

  6. 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 ...

  7. ASP.NET vNext:微软下一代云环境Web开发框架

    作者 郭蕾 发布于 2014年5月16日   在5月12日的TechED大会上,微软首次向外界介绍了下一代ASP.NET框架——ASP.NET vNext.ASP.NET vNext专门针对云环境和服 ...

  8. Asp.net vNext 学习之路(一)

    概述 asp.net vNext 也叫 asp.net 5.0,意思是微软推出的下一个版本的asp.net.可以说是微软对asp.net的一个比较重大的重新设计, asp.net vNext是一 个比 ...

  9. ASP.NET vNext 微笔记

    关心 ASP.NET vNext 的人可能已经读过相关文章,例如:ASP.NET vNext @ 2014.那么,你可能已经知道,ASP.NET vNext 摆脱了 System.Web.DLL,把 ...

随机推荐

  1. __metaclass__ 实现单列模式

    class Singleton(type): """Singleton. @see: http://stackoverflow.com/questions/6760685 ...

  2. Hadoop生态圈-hive优化手段-作业和查询优化

    Hadoop生态圈-hive优化手段-作业和查询优化 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.

  3. mongo查询日期格式数据

    /ali/mongodb/bin/mongo -u user -p '123456' 127.0.0.1:27017/KYElog ISODate方式 db.col_02.find({"Lo ...

  4. 将输出语句打印至tomcat日志文件中

    tomcat-9.0.0 将程序中            System.out.println("------------这是输出语句System.out.println()-------- ...

  5. 应用jfinal发送微信模板消息的一个bug

    严格来讲,这不是一个bug,只是我们应用的方式不对.微信发送模板消息的方法是: HttpUtils.post(sendApiUrl + AccessTokenApi.getAccessTokenStr ...

  6. [洛谷P4491] [HAOI2018]染色

    洛谷题目链接:[HAOI2018]染色 题目背景 HAOI2018 Round2 第二题 题目描述 为了报答小 C 的苹果, 小 G 打算送给热爱美术的小 C 一块画布, 这块画布可 以抽象为一个长度 ...

  7. React - 环境准备

    1. 下载 node.js,在 https://nodejs.org/en/download/ 选择合适的版本. 2. 检查 node.js 是否安装成功. hueyMB:~ zhisenzheng$ ...

  8. ElasticSearch关键概念

    Elasticsearch 添加索引 一个存储关联数据的地方 用来指向一个或者多个分片(shards)的逻辑命名空间(logical namespcase) 应用程序直接与索引通信 一个分片(shar ...

  9. [转载]RSA算法详解

    原文:http://www.matrix67.com/blog/archives/5100 数论,数学中的皇冠,最纯粹的数学.早在古希腊时代,人们就开始痴迷地研究数字,沉浸于这个几乎没有任何实用价值的 ...

  10. Samba远程代码执行漏洞(CVE-2017-7494)复现

    简要记录一下Samba远程代码执行漏洞(CVE-2017-7494)环境搭建和利用的过程,献给那些想自己动手搭建环境的朋友.(虽然已过多时) 快捷通道:Docker ~ Samba远程代码执行漏洞(C ...