不太会排版,大家将就看吧.
asp.net core mvc和asp.net mvc中都有一个比较有意思的而又被大家容易忽略的功能,控制器可以写在非Web程序集中,比如Web程序集:"MyWeb",引用程序集"B.bll",你可以将所有的控制器写在"B.bll"程序集里面.mvc框架仍然可以寻找到这个控制器.
仔细想一想,mvc框架启动的时候寻找过程:1.找到所有包含控制器的程序集;2.反射找到所有控制器类型;3.反射找到所有的action;4.缓存这些controller与action.
那么有意思的就是第一步"找到所有包含控制器的程序集",一开始我认为是扫描当前应用程序域已加载的程序集,然后反射判断存不存在控制器类型.单如果一个程序有上千个程序集,那么反射无疑是一种灾难,mvc的启动也没这么慢啊,怀着好奇的心,这里就扒一扒官方的实现原理(asp.net mvc源码没去看,但原理估计差不多,这里就扒asp.net core mvc).
这里建议大家先了解下 asp.net core mvc的启动流程:http://www.cnblogs.com/savorboard/p/aspnetcore-mvc-startup.html.
action的匹配:http://www.cnblogs.com/savorboard/p/aspnetcore-mvc-routing-action.html
这里引用杨晓东博客中的图片:
1.AddMvcCore,mvc核心启动代码:
public static IMvcCoreBuilder AddMvcCore(this IServiceCollection services) { if (services == null) { throw new ArgumentNullException(nameof(services)); } //获取ApplicationPartManager管理类,该类保存了ApplicationPart集合,而ApplicationPart最重要的子类AssemblyPart记录了程序集信息,另外PopulateFeature用于填充各种功能 var partManager = GetApplicationPartManager(services); services.TryAddSingleton(partManager); ConfigureDefaultFeatureProviders(partManager); ConfigureDefaultServices(services); AddMvcCoreServices(services); var builder = new MvcCoreBuilder(services, partManager); return builder; }
ApplicationPartManager:
/// <summary> /// Manages the parts and features of an MVC application. /// </summary> public class ApplicationPartManager { /// <summary> /// Gets the list of <see cref="IApplicationFeatureProvider"/>s. /// </summary> public IList<IApplicationFeatureProvider> FeatureProviders { get; } = new List<IApplicationFeatureProvider>(); /// <summary> /// Gets the list of <see cref="ApplicationPart"/>s. /// </summary> public IList<ApplicationPart> ApplicationParts { get; } = new List<ApplicationPart>(); /// <summary> /// Populates the given <paramref name="feature"/> using the list of /// <see cref="IApplicationFeatureProvider{TFeature}"/>s configured on the /// <see cref="ApplicationPartManager"/>. /// </summary> /// <typeparam name="TFeature">The type of the feature.</typeparam> /// <param name="feature">The feature instance to populate.</param> public void PopulateFeature<TFeature>(TFeature feature) { if (feature == null) { throw new ArgumentNullException(nameof(feature)); } foreach (var provider in FeatureProviders.OfType<IApplicationFeatureProvider<TFeature>>()) { provider.PopulateFeature(ApplicationParts, feature); } } }