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讲解

 

如果你对我的文章有疑问,希望你可以在下方评论区留言。我会抽空为你解答。

如果你觉得我的文章还不错,希望能分享出去。让更多的朋友一起共同学习。你们的认可,是我分享的动力。

 

posted @ 2016-10-13 16:43  AntColony  阅读(1680)  评论(0编辑  收藏  举报