Orchard剖析开篇之依赖注入Autofac
在Orchard中大量使用Autofac依赖注入,所以讲解Orchard之前,这个是必不可少的。
首先,我们先来看看Orchard.Web项目下的Glogal文件。
文件中,我们看到如下代码:
1 public class MvcApplication : HttpApplication { 2 private static Starter<IOrchardHost> _starter; 3 4 public MvcApplication() { 5 } 6 7 public static void RegisterRoutes(RouteCollection routes) { 8 routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 9 } 10 11 protected void Application_Start() { 12 RegisterRoutes(RouteTable.Routes); 13 _starter = new Starter<IOrchardHost>(HostInitialization, HostBeginRequest, HostEndRequest); 14 _starter.OnApplicationStart(this); 15 } 16 17 protected void Application_BeginRequest() { 18 _starter.OnBeginRequest(this); 19 } 20 21 protected void Application_EndRequest() { 22 _starter.OnEndRequest(this); 23 } 24 25 private static void HostBeginRequest(HttpApplication application, IOrchardHost host) { 26 application.Context.Items["originalHttpContext"] = application.Context; 27 host.BeginRequest(); 28 } 29 30 private static void HostEndRequest(HttpApplication application, IOrchardHost host) { 31 host.EndRequest(); 32 } 33 34 private static IOrchardHost HostInitialization(HttpApplication application) { 35 var host = OrchardStarter.CreateHost(MvcSingletons); 36 37 host.Initialize(); 38 39 // initialize shells to speed up the first dynamic query 40 host.BeginRequest(); 41 host.EndRequest(); 42 43 return host; 44 } 45 46 static void MvcSingletons(ContainerBuilder builder) { 47 builder.Register(ctx => RouteTable.Routes).SingleInstance(); 48 builder.Register(ctx => ModelBinders.Binders).SingleInstance(); 49 builder.Register(ctx => ViewEngines.Engines).SingleInstance(); 50 } 51 }
好了,现在我们来分析下这里面的代码。
首先我们先看下Application_Start()函数,这个是站点的启动入口
在这个函数里,我们可以看到函数里对一个静态的Starter启动器进行了初始化。
好了,接下里我们来看下Starter这个启动器的构造函数。
从Starter的构造函数,我们可以发现构造函数声明了三个委托,分别用于处理程序初始化,接收到请求以及请求处理结束时触发的事件。
看到这里,我们也知道了这三个委托声明的含义了。
那么,接下类。我们回到Application_Start()函数中来。
我们先看下HostInitialization委托的实现。
委托主要是实现了Orchard宿主的创建以及初始化工作。
细心的朋友可能已经发现了,Orchard宿主的实例工作是由一个静态的OrchardStarter类的一个创建宿主的接口来执行的。
既然如此,我们就来看看这个接口到底做了哪些事。
观察CreateHost接口,我们发现里面有一个CreateHostContainer的接口。它创建了一个容器IContainer对象,然后从容器中解析出宿主返回回去。
看到这里,我相信认真的朋友应该可以看出来了。作者在IContainer容器内注册了IOrchardHost宿主的实现方式,所以客户端可以通过这个容器去获得IOrchardHost宿主。
可能也有的朋友到这里有疑惑,IContainer是个什么东西。
那好,我这里给大家说明一下。
IContainer是Autofac提供的一个容器,这个容器由Autofac的构建者ContainerBuilder对象构建出来的。而ContainerBuilder有怎么知道实例怎么实现呢。
那么,接下来我们就来看下CreateHostContainer这个接口,看完后,相信大家就能豁然开然了。
1 public static IContainer CreateHostContainer(Action<ContainerBuilder> registrations) { 2 ExtensionLocations extensionLocations = new ExtensionLocations(); 3 4 var builder = new ContainerBuilder(); 5 // Application paths and parameters 6 builder.RegisterInstance(extensionLocations); 7 8 builder.RegisterModule(new CollectionOrderModule()); 9 builder.RegisterModule(new LoggingModule()); 10 builder.RegisterModule(new EventsModule()); 11 builder.RegisterModule(new CacheModule()); 12 13 // a single default host implementation is needed for bootstrapping a web app domain 14 builder.RegisterType<DefaultOrchardEventBus>().As<IEventBus>().SingleInstance(); 15 builder.RegisterType<DefaultCacheHolder>().As<ICacheHolder>().SingleInstance(); 16 builder.RegisterType<DefaultCacheContextAccessor>().As<ICacheContextAccessor>().SingleInstance(); 17 builder.RegisterType<DefaultParallelCacheContext>().As<IParallelCacheContext>().SingleInstance(); 18 builder.RegisterType<DefaultAsyncTokenProvider>().As<IAsyncTokenProvider>().SingleInstance(); 19 builder.RegisterType<DefaultHostEnvironment>().As<IHostEnvironment>().SingleInstance(); 20 builder.RegisterType<DefaultHostLocalRestart>().As<IHostLocalRestart>().Named<IEventHandler>(typeof(IShellSettingsManagerEventHandler).Name).SingleInstance(); 21 builder.RegisterType<DefaultBuildManager>().As<IBuildManager>().SingleInstance(); 22 builder.RegisterType<DynamicModuleVirtualPathProvider>().As<ICustomVirtualPathProvider>().SingleInstance(); 23 builder.RegisterType<AppDataFolderRoot>().As<IAppDataFolderRoot>().SingleInstance(); 24 builder.RegisterType<DefaultExtensionCompiler>().As<IExtensionCompiler>().SingleInstance(); 25 builder.RegisterType<DefaultRazorCompilationEvents>().As<IRazorCompilationEvents>().SingleInstance(); 26 builder.RegisterType<DefaultProjectFileParser>().As<IProjectFileParser>().SingleInstance(); 27 builder.RegisterType<DefaultAssemblyLoader>().As<IAssemblyLoader>().SingleInstance(); 28 builder.RegisterType<AppDomainAssemblyNameResolver>().As<IAssemblyNameResolver>().SingleInstance(); 29 builder.RegisterType<GacAssemblyNameResolver>().As<IAssemblyNameResolver>().SingleInstance(); 30 builder.RegisterType<OrchardFrameworkAssemblyNameResolver>().As<IAssemblyNameResolver>().SingleInstance(); 31 builder.RegisterType<HttpContextAccessor>().As<IHttpContextAccessor>().InstancePerDependency(); 32 builder.RegisterType<ViewsBackgroundCompilation>().As<IViewsBackgroundCompilation>().SingleInstance(); 33 builder.RegisterType<DefaultExceptionPolicy>().As<IExceptionPolicy>().SingleInstance(); 34 builder.RegisterType<DefaultCriticalErrorProvider>().As<ICriticalErrorProvider>().SingleInstance(); 35 //builder.RegisterType<RazorTemplateCache>().As<IRazorTemplateProvider>().SingleInstance(); 36 37 RegisterVolatileProvider<WebSiteFolder, IWebSiteFolder>(builder); 38 RegisterVolatileProvider<AppDataFolder, IAppDataFolder>(builder); 39 RegisterVolatileProvider<DefaultLockFileManager, ILockFileManager>(builder); 40 RegisterVolatileProvider<Clock, IClock>(builder); 41 RegisterVolatileProvider<DefaultDependenciesFolder, IDependenciesFolder>(builder); 42 RegisterVolatileProvider<DefaultExtensionDependenciesManager, IExtensionDependenciesManager>(builder); 43 RegisterVolatileProvider<DefaultAssemblyProbingFolder, IAssemblyProbingFolder>(builder); 44 RegisterVolatileProvider<DefaultVirtualPathMonitor, IVirtualPathMonitor>(builder); 45 RegisterVolatileProvider<DefaultVirtualPathProvider, IVirtualPathProvider>(builder); 46 47 builder.RegisterType<DefaultOrchardHost>().As<IOrchardHost>().As<IEventHandler>() 48 .Named<IEventHandler>(typeof(IShellSettingsManagerEventHandler).Name) 49 .Named<IEventHandler>(typeof(IShellDescriptorManagerEventHandler).Name) 50 .SingleInstance(); 51 { 52 builder.RegisterType<ShellSettingsManager>().As<IShellSettingsManager>().SingleInstance(); 53 54 builder.RegisterType<ShellContextFactory>().As<IShellContextFactory>().SingleInstance(); 55 { 56 builder.RegisterType<ShellDescriptorCache>().As<IShellDescriptorCache>().SingleInstance(); 57 58 builder.RegisterType<CompositionStrategy>().As<ICompositionStrategy>().SingleInstance(); 59 { 60 builder.RegisterType<ShellContainerRegistrations>().As<IShellContainerRegistrations>().SingleInstance(); 61 builder.RegisterType<ExtensionLoaderCoordinator>().As<IExtensionLoaderCoordinator>().SingleInstance(); 62 builder.RegisterType<ExtensionMonitoringCoordinator>().As<IExtensionMonitoringCoordinator>().SingleInstance(); 63 builder.RegisterType<ExtensionManager>().As<IExtensionManager>().SingleInstance(); 64 { 65 builder.RegisterType<ExtensionHarvester>().As<IExtensionHarvester>().SingleInstance(); 66 builder.RegisterType<ModuleFolders>().As<IExtensionFolders>().SingleInstance() 67 .WithParameter(new NamedParameter("paths", extensionLocations.ModuleLocations)); 68 builder.RegisterType<CoreModuleFolders>().As<IExtensionFolders>().SingleInstance() 69 .WithParameter(new NamedParameter("paths", extensionLocations.CoreLocations)); 70 builder.RegisterType<ThemeFolders>().As<IExtensionFolders>().SingleInstance() 71 .WithParameter(new NamedParameter("paths", extensionLocations.ThemeLocations)); 72 73 builder.RegisterType<CoreExtensionLoader>().As<IExtensionLoader>().SingleInstance(); 74 builder.RegisterType<ReferencedExtensionLoader>().As<IExtensionLoader>().SingleInstance(); 75 builder.RegisterType<PrecompiledExtensionLoader>().As<IExtensionLoader>().SingleInstance(); 76 builder.RegisterType<DynamicExtensionLoader>().As<IExtensionLoader>().SingleInstance(); 77 builder.RegisterType<RawThemeExtensionLoader>().As<IExtensionLoader>().SingleInstance(); 78 } 79 } 80 81 builder.RegisterType<ShellContainerFactory>().As<IShellContainerFactory>().SingleInstance(); 82 } 83 84 builder.RegisterType<DefaultProcessingEngine>().As<IProcessingEngine>().SingleInstance(); 85 } 86 87 builder.RegisterType<RunningShellTable>().As<IRunningShellTable>().SingleInstance(); 88 builder.RegisterType<DefaultOrchardShell>().As<IOrchardShell>().InstancePerMatchingLifetimeScope("shell"); 89 builder.RegisterType<SessionConfigurationCache>().As<ISessionConfigurationCache>().InstancePerMatchingLifetimeScope("shell"); 90 91 registrations(builder); 92 93 var autofacSection = ConfigurationManager.GetSection(ConfigurationSettingsReaderConstants.DefaultSectionName); 94 if (autofacSection != null) 95 builder.RegisterModule(new ConfigurationSettingsReader()); 96 97 var optionalHostConfig = HostingEnvironment.MapPath("~/Config/Host.config"); 98 if (File.Exists(optionalHostConfig)) 99 builder.RegisterModule(new ConfigurationSettingsReader(ConfigurationSettingsReaderConstants.DefaultSectionName, optionalHostConfig)); 100 101 var optionalComponentsConfig = HostingEnvironment.MapPath("~/Config/HostComponents.config"); 102 if (File.Exists(optionalComponentsConfig)) 103 builder.RegisterModule(new HostComponentsConfigModule(optionalComponentsConfig)); 104 105 var container = builder.Build(); 106 107 // 108 // Register Virtual Path Providers 109 // 110 if (HostingEnvironment.IsHosted) { 111 foreach (var vpp in container.Resolve<IEnumerable<ICustomVirtualPathProvider>>()) { 112 HostingEnvironment.RegisterVirtualPathProvider(vpp.Instance); 113 } 114 } 115 116 ControllerBuilder.Current.SetControllerFactory(new OrchardControllerFactory()); 117 FilterProviders.Providers.Add(new OrchardFilterProvider()); 118 119 GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerSelector), new DefaultOrchardWebApiHttpControllerSelector(GlobalConfiguration.Configuration)); 120 GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerActivator), new DefaultOrchardWebApiHttpControllerActivator(GlobalConfiguration.Configuration)); 121 GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container); 122 123 GlobalConfiguration.Configuration.Filters.Add(new OrchardApiActionFilterDispatcher()); 124 GlobalConfiguration.Configuration.Filters.Add(new OrchardApiExceptionFilterDispatcher()); 125 GlobalConfiguration.Configuration.Filters.Add(new OrchardApiAuthorizationFilterDispatcher()); 126 127 ViewEngines.Engines.Clear(); 128 ViewEngines.Engines.Add(new ThemeAwareViewEngineShim()); 129 130 var hostContainer = new DefaultOrchardHostContainer(container); 131 //MvcServiceLocator.SetCurrent(hostContainer); 132 OrchardHostContainerRegistry.RegisterHostContainer(hostContainer); 133 134 // Register localized data annotations 135 ModelValidatorProviders.Providers.Clear(); 136 ModelValidatorProviders.Providers.Add(new LocalizedModelValidatorProvider()); 137 138 return container; 139 }
这个接口代码有点多,朋友们看起来应该有点累。所以我简化一下大概代码如下
1 public static IContainer CreateHostContainer(Action<ContainerBuilder> registrations) 2 { 3 var builder = new ContainerBuilder(); 4 //to do register 5 6 //builder.RegisterInstance() 7 8 //builder.RegisterModule(); 9 10 //builder.RegisterType<>().As<>().SingleInstance(); 11 12 //builder.RegisterType<>().As<>().InstancePerDependency(); 13 14 //to do register delegate Method 15 registrations(builder); 16 17 var container = builder.Build(); 18 19 //to do register virtual path providers 20 21 22 return container; 23 }
通过观察上面这段代码,可以看出来。
这个接口就做了几件事:
1.初始化IOC构建器ContainerBuilder
2.依赖注入注册约定
3.构建容器IContainer
这个接口不过是做了很多关于IOC依赖注入的注册工作。
Autofac在Orchard框架中扮演了一个很重要的角色,Autofac为Orchard框架提供了很高的扩展性。
相关的IOC依赖注入大家可以看下http://www.cnblogs.com/xrainchen/articles/5962993.html
好了,开篇介绍工作就讲到这里。
下一篇:Orchard.Cache讲解
如果你对我的文章有疑问,希望你可以在下方评论区留言。我会抽空为你解答。
如果你觉得我的文章还不错,希望能分享出去。让更多的朋友一起共同学习。你们的认可,是我分享的动力。