Orchard详解--第三篇 依赖注入之基础设施
private static IOrchardHost HostInitialization(HttpApplication application) {
var host = OrchardStarter.CreateHost(MvcSingletons);
host.Initialize();
// initialize shells to speed up the first dynamic query
host.BeginRequest();
host.EndRequest();
return host;
}
其中OrchardStarter是位于Orchard.Framework项目中Environment目录下的类型
public static IOrchardHost CreateHost(Action<ContainerBuilder> registrations) {
var container = CreateHostContainer(registrations);
return container.Resolve<IOrchardHost>();
}
public static IContainer CreateHostContainer(Action<ContainerBuilder> registrations) {
ExtensionLocations extensionLocations = new ExtensionLocations();
var builder = new ContainerBuilder();
// Application paths and parameters
builder.RegisterInstance(extensionLocations);
builder.RegisterModule(new CollectionOrderModule());
builder.RegisterModule(new LoggingModule());
builder.RegisterModule(new EventsModule());
builder.RegisterModule(new CacheModule());
// a single default host implementation is needed for bootstrapping a web app domain
builder.RegisterType<DefaultOrchardEventBus>().As<IEventBus>().SingleInstance();
builder.RegisterType<DefaultCacheHolder>().As<ICacheHolder>().SingleInstance();
builder.RegisterType<DefaultCacheContextAccessor>().As<ICacheContextAccessor>().SingleInstance();
builder.RegisterType<DefaultParallelCacheContext>().As<IParallelCacheContext>().SingleInstance();
builder.RegisterType<DefaultAsyncTokenProvider>().As<IAsyncTokenProvider>().SingleInstance();
builder.RegisterType<DefaultHostEnvironment>().As<IHostEnvironment>().SingleInstance();
builder.RegisterType<DefaultHostLocalRestart>().As<IHostLocalRestart>().Named<IEventHandler>(typeof(IShellSettingsManagerEventHandler).Name).SingleInstance();
builder.RegisterType<DefaultBuildManager>().As<IBuildManager>().SingleInstance();
builder.RegisterType<DynamicModuleVirtualPathProvider>().As<ICustomVirtualPathProvider>().SingleInstance();
builder.RegisterType<AppDataFolderRoot>().As<IAppDataFolderRoot>().SingleInstance();
builder.RegisterType<DefaultExtensionCompiler>().As<IExtensionCompiler>().SingleInstance();
builder.RegisterType<DefaultRazorCompilationEvents>().As<IRazorCompilationEvents>().SingleInstance();
builder.RegisterType<DefaultProjectFileParser>().As<IProjectFileParser>().SingleInstance();
builder.RegisterType<DefaultAssemblyLoader>().As<IAssemblyLoader>().SingleInstance();
builder.RegisterType<AppDomainAssemblyNameResolver>().As<IAssemblyNameResolver>().SingleInstance();
builder.RegisterType<GacAssemblyNameResolver>().As<IAssemblyNameResolver>().SingleInstance();
builder.RegisterType<OrchardFrameworkAssemblyNameResolver>().As<IAssemblyNameResolver>().SingleInstance();
builder.RegisterType<HttpContextAccessor>().As<IHttpContextAccessor>().InstancePerDependency();
builder.RegisterType<ViewsBackgroundCompilation>().As<IViewsBackgroundCompilation>().SingleInstance();
builder.RegisterType<DefaultExceptionPolicy>().As<IExceptionPolicy>().SingleInstance();
builder.RegisterType<DefaultCriticalErrorProvider>().As<ICriticalErrorProvider>().SingleInstance();
//builder.RegisterType<RazorTemplateCache>().As<IRazorTemplateProvider>().SingleInstance();
RegisterVolatileProvider<WebSiteFolder, IWebSiteFolder>(builder);
RegisterVolatileProvider<AppDataFolder, IAppDataFolder>(builder);
RegisterVolatileProvider<DefaultLockFileManager, ILockFileManager>(builder);
RegisterVolatileProvider<Clock, IClock>(builder);
RegisterVolatileProvider<DefaultDependenciesFolder, IDependenciesFolder>(builder);
RegisterVolatileProvider<DefaultExtensionDependenciesManager, IExtensionDependenciesManager>(builder);
RegisterVolatileProvider<DefaultAssemblyProbingFolder, IAssemblyProbingFolder>(builder);
RegisterVolatileProvider<DefaultVirtualPathMonitor, IVirtualPathMonitor>(builder);
RegisterVolatileProvider<DefaultVirtualPathProvider, IVirtualPathProvider>(builder);
builder.RegisterType<DefaultOrchardHost>().As<IOrchardHost>().As<IEventHandler>()
.Named<IEventHandler>(typeof(IShellSettingsManagerEventHandler).Name)
.Named<IEventHandler>(typeof(IShellDescriptorManagerEventHandler).Name)
.SingleInstance();
{
builder.RegisterType<ShellSettingsManager>().As<IShellSettingsManager>().SingleInstance();
builder.RegisterType<ShellContextFactory>().As<IShellContextFactory>().SingleInstance();
{
builder.RegisterType<ShellDescriptorCache>().As<IShellDescriptorCache>().SingleInstance();
builder.RegisterType<CompositionStrategy>().As<ICompositionStrategy>().SingleInstance();
{
builder.RegisterType<ShellContainerRegistrations>().As<IShellContainerRegistrations>().SingleInstance();
builder.RegisterType<ExtensionLoaderCoordinator>().As<IExtensionLoaderCoordinator>().SingleInstance();
builder.RegisterType<ExtensionMonitoringCoordinator>().As<IExtensionMonitoringCoordinator>().SingleInstance();
builder.RegisterType<ExtensionManager>().As<IExtensionManager>().SingleInstance();
{
builder.RegisterType<ExtensionHarvester>().As<IExtensionHarvester>().SingleInstance();
builder.RegisterType<ModuleFolders>().As<IExtensionFolders>().SingleInstance()
.WithParameter(new NamedParameter("paths", extensionLocations.ModuleLocations));
builder.RegisterType<CoreModuleFolders>().As<IExtensionFolders>().SingleInstance()
.WithParameter(new NamedParameter("paths", extensionLocations.CoreLocations));
builder.RegisterType<ThemeFolders>().As<IExtensionFolders>().SingleInstance()
.WithParameter(new NamedParameter("paths", extensionLocations.ThemeLocations));
builder.RegisterType<CoreExtensionLoader>().As<IExtensionLoader>().SingleInstance();
builder.RegisterType<ReferencedExtensionLoader>().As<IExtensionLoader>().SingleInstance();
builder.RegisterType<PrecompiledExtensionLoader>().As<IExtensionLoader>().SingleInstance();
builder.RegisterType<DynamicExtensionLoader>().As<IExtensionLoader>().SingleInstance();
builder.RegisterType<RawThemeExtensionLoader>().As<IExtensionLoader>().SingleInstance();
}
}
builder.RegisterType<ShellContainerFactory>().As<IShellContainerFactory>().SingleInstance();
}
builder.RegisterType<DefaultProcessingEngine>().As<IProcessingEngine>().SingleInstance();
}
builder.RegisterType<RunningShellTable>().As<IRunningShellTable>().SingleInstance();
builder.RegisterType<DefaultOrchardShell>().As<IOrchardShell>().InstancePerMatchingLifetimeScope("shell");
builder.RegisterType<SessionConfigurationCache>().As<ISessionConfigurationCache>().InstancePerMatchingLifetimeScope("shell");
registrations(builder);
var autofacSection = ConfigurationManager.GetSection(ConfigurationSettingsReaderConstants.DefaultSectionName);
if (autofacSection != null)
builder.RegisterModule(new ConfigurationSettingsReader());
var optionalHostConfig = HostingEnvironment.MapPath("~/Config/Host.config");
if (File.Exists(optionalHostConfig))
builder.RegisterModule(new ConfigurationSettingsReader(ConfigurationSettingsReaderConstants.DefaultSectionName, optionalHostConfig));
var optionalComponentsConfig = HostingEnvironment.MapPath("~/Config/HostComponents.config");
if (File.Exists(optionalComponentsConfig))
builder.RegisterModule(new HostComponentsConfigModule(optionalComponentsConfig));
var container = builder.Build();
//
// Register Virtual Path Providers
//
if (HostingEnvironment.IsHosted) {
foreach (var vpp in container.Resolve<IEnumerable<ICustomVirtualPathProvider>>()) {
HostingEnvironment.RegisterVirtualPathProvider(vpp.Instance);
}
}
ControllerBuilder.Current.SetControllerFactory(new OrchardControllerFactory());
FilterProviders.Providers.Add(new OrchardFilterProvider());
GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerSelector), new DefaultOrchardWebApiHttpControllerSelector(GlobalConfiguration.Configuration));
GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerActivator), new DefaultOrchardWebApiHttpControllerActivator(GlobalConfiguration.Configuration));
GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container);
GlobalConfiguration.Configuration.Filters.Add(new OrchardApiActionFilterDispatcher());
GlobalConfiguration.Configuration.Filters.Add(new OrchardApiExceptionFilterDispatcher());
GlobalConfiguration.Configuration.Filters.Add(new OrchardApiAuthorizationFilterDispatcher());
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new ThemeAwareViewEngineShim());
var hostContainer = new DefaultOrchardHostContainer(container);
//MvcServiceLocator.SetCurrent(hostContainer);
OrchardHostContainerRegistry.RegisterHostContainer(hostContainer);
// Register localized data annotations
ModelValidatorProviders.Providers.Clear();
ModelValidatorProviders.Providers.Add(new LocalizedModelValidatorProvider());
return container;
}
- 基础组件:日志、事件、缓存
- 环境相关:路径、程序集、编译器,Http上下文
- 异常处理:异常策略
- 拓展相关:拓展目录、拓展依赖、拓展管理。
- 多租户相关:Shell表、Shell启动。
- 拓展的依赖注入:拓展模块中的自定义注入、Host及HostComponents配置文件的注入。
- MVC相关:ControllerFactory替换,过滤器加载
- WebAPI相关:Selector、Activator替换,DependencyResolver替换、过滤器加载
- ViewEngine:使用ThemeAwareViewEngineShim。
- Model相关:使用LocalizedModelValidatorProvider作为Model验证器。
- 日志的自动属性注入:
protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration) {
var implementationType = registration.Activator.LimitType;
// build an array of actions on this type to assign loggers to member properties
var injectors = BuildLoggerInjectors(implementationType).ToArray();
// if there are no logger properties, there's no reason to hook the activated event
if (!injectors.Any())
return;
// otherwise, whan an instance of this component is activated, inject the loggers on the instance
registration.Activated += (s, e) => {
foreach (var injector in injectors)
injector(e.Context, e.Instance);
};
}
private IEnumerable<Action<IComponentContext, object>> BuildLoggerInjectors(Type componentType) {
// Look for settable properties of type "ILogger"
var loggerProperties = componentType
.GetProperties(BindingFlags.SetProperty | BindingFlags.Public | BindingFlags.Instance)
.Select(p => new {
PropertyInfo = p,
p.PropertyType,
IndexParameters = p.GetIndexParameters(),
Accessors = p.GetAccessors(false)
})
.Where(x => x.PropertyType == typeof(ILogger)) // must be a logger
.Where(x => x.IndexParameters.Count() == ) // must not be an indexer
.Where(x => x.Accessors.Length != || x.Accessors[].ReturnType == typeof(void)); //must have get/set, or only set
// Return an array of actions that resolve a logger and assign the property
foreach (var entry in loggerProperties) {
var propertyInfo = entry.PropertyInfo;
yield return (ctx, instance) => {
string component = componentType.ToString();
if (component != instance.GetType().ToString()) {
return;
}
var logger = _loggerCache.GetOrAdd(component, key => ctx.Resolve<ILogger>(new TypedParameter(typeof(Type), componentType)));
propertyInfo.SetValue(instance, logger, null);
};
}
}
其实它的核心就是注册时通过对象类型查找是否有一个类型为Ilogger的可读写属性,拿出来赋值。
2. 通过动态代理实现的事件机制:
public interface IBoilHandler : IEventHandler
{
void OnTemperatureChanged(int temperature);
}
// 热水器
public class Heater
{
private int temperature;
private IBoilHandler _boilhandler;
public Heater(IBoilHandler boilhandler)
{
_boilhandler = boilhandler;
}
// 烧水
public void BoilWater()
{
for (int i = ; i <= ; i++)
{
temperature = i;
if (temperature > )
{
if (_boilhandler != null)
{ //如果有对象注册
_boilhandler.OnTemperatureChanged(temperature); //调用所有注册对象的方法
}
}
}
}
}
// 警报器
public class Alarm : IBoilHandler
{
public void OnTemperatureChanged(int temperature)
{
Console.WriteLine("Alarm:嘀嘀嘀,水已经 {0} 度了:", temperature);
}
}
// 显示器
public class Display : IBoilHandler
{
public void OnTemperatureChanged(int temperature)
{
Console.WriteLine("Display:水快烧开了,当前温度:{0}度。", temperature);
}
}
public class EventsRegistrationSource : IRegistrationSource {
private readonly DefaultProxyBuilder _proxyBuilder;
public EventsRegistrationSource() {
_proxyBuilder = new DefaultProxyBuilder();
}
public bool IsAdapterForIndividualComponents {
get { return false; }
}
public IEnumerable<IComponentRegistration> RegistrationsFor(Service service, Func<Service, IEnumerable<IComponentRegistration>> registrationAccessor) {
var serviceWithType = service as IServiceWithType;
if (serviceWithType == null)
yield break;
var serviceType = serviceWithType.ServiceType;
if (!serviceType.IsInterface || !typeof(IEventHandler).IsAssignableFrom(serviceType) || serviceType == typeof(IEventHandler))
yield break;
var interfaceProxyType = _proxyBuilder.CreateInterfaceProxyTypeWithoutTarget(
serviceType,
new Type[],
ProxyGenerationOptions.Default);
var rb = RegistrationBuilder
.ForDelegate((ctx, parameters) => {
var interceptors = new IInterceptor[] { new EventsInterceptor(ctx.Resolve<IEventBus>()) };
var args = new object[] { interceptors, null };
return Activator.CreateInstance(interfaceProxyType, args);
})
.As(service);
yield return rb.CreateRegistration();
}
}
public class EventsInterceptor : IInterceptor {
private readonly IEventBus _eventBus;
private static readonly ConcurrentDictionary<Type,MethodInfo> _enumerableOfTypeTDictionary = new ConcurrentDictionary<Type, MethodInfo>();
public EventsInterceptor(IEventBus eventBus) {
_eventBus = eventBus;
}
public void Intercept(IInvocation invocation) {
var interfaceName = invocation.Method.DeclaringType.Name;
var methodName = invocation.Method.Name;
var data = invocation.Method.GetParameters()
.Select((parameter, index) => new { parameter.Name, Value = invocation.Arguments[index] })
.ToDictionary(kv => kv.Name, kv => kv.Value);
var results = _eventBus.Notify(interfaceName + "." + methodName, data);
invocation.ReturnValue = Adjust(results, invocation.Method.ReturnType);
}
public static object Adjust(IEnumerable results, Type returnType) {
if (returnType == typeof(void) ||
results == null ||
results.GetType() == returnType) {
return results;
}
// acquire method:
// static IEnumerable<T> IEnumerable.OfType<T>(this IEnumerable source)
// where T is from returnType's IEnumerable<T>
var enumerableOfTypeT = _enumerableOfTypeTDictionary.GetOrAdd( returnType, type => typeof(Enumerable).GetGenericMethod("OfType", type.GetGenericArguments(), new[] { typeof(IEnumerable) }, typeof(IEnumerable<>)));
return enumerableOfTypeT.Invoke(null, new[] { results });
}
}
上面代码有个重点就是:
if (!serviceType.IsInterface || !typeof(IEventHandler).IsAssignableFrom(serviceType) || serviceType == typeof(IEventHandler))
yield break;
如果不是接口、如果类型不是IEventHandler的子类型(子接口)且当前类型就是IEventHandler,满足这三个接口就跳出。正过来说就是:
- 类型一定是接口
- 一定是继承IEventHandler的接口
- 一定不是IEventHandler本身
if (typeof(IEventHandler).IsAssignableFrom(item.Type)) {
var interfaces = item.Type.GetInterfaces();
foreach (var interfaceType in interfaces) {
// register named instance for each interface, for efficient filtering inside event bus
// IEventHandler derived classes only
if (interfaceType.GetInterface(typeof (IEventHandler).Name) != null) {
registration = registration.Named<IEventHandler>(interfaceType.Name);
}
}
}
protected override void AttachToComponentRegistration(Autofac.Core.IComponentRegistry componentRegistry, Autofac.Core.IComponentRegistration registration) {
var needsCacheManager = registration.Activator.LimitType
.GetConstructors()
.Any(x => x.GetParameters()
.Any(xx => xx.ParameterType == typeof(ICacheManager)));
if (needsCacheManager) {
registration.Preparing += (sender, e) => {
var parameter = new TypedParameter(
typeof(ICacheManager),
e.Context.Resolve<ICacheManager>(new TypedParameter(typeof(Type), registration.Activator.LimitType)));
e.Parameters = e.Parameters.Concat(new[] { parameter });
};
}
}
Orchard详解--第三篇 依赖注入之基础设施的更多相关文章
- Java程序员从笨鸟到菜鸟之(一百零二)sql注入攻击详解(三)sql注入解决办法
sql注入攻击详解(二)sql注入过程详解 sql注入攻击详解(一)sql注入原理详解 我们了解了sql注入原理和sql注入过程,今天我们就来了解一下sql注入的解决办法.怎么来解决和防范sql注入, ...
- 详解AngularJS中的依赖注入
点击查看AngularJS系列目录 依赖注入 一般来说,一个对象只能通过三种方法来得到它的依赖项目: 我们可以在对象内部创建依赖项目 我们可以将依赖作为一个全局变量来进行查找或引用 我们可以将依赖传递 ...
- 详解Java Spring各种依赖注入注解的区别
注解注入顾名思义就是通过注解来实现注入,Spring和注入相关的常见注解有Autowired.Resource.Qualifier.Service.Controller.Repository.Comp ...
- ASP.NET Core 学习笔记 第三篇 依赖注入框架的使用
前言 首先感谢小可爱门的支持,写了这个系列的第二篇后,得到了好多人的鼓励,也更加坚定我把这个系列写完的决心,也能更好的督促自己的学习,分享自己的学习成果.还记得上篇文章中最后提及到,假如服务越来越多怎 ...
- 【laravel5.*】详解laravel中的依赖注入
1.下面这个是自定义的类,钉钉扫码登录web 网页授权OAuth2.0,是一个典型的依赖注入参考示例:
- Orchard详解--第八篇 拓展模块及引用的预处理
从上一篇可以看出Orchard在处理拓展模块时主要有两个组件,一个是Folder另一个是Loader,前者用于搜索后者用于加载. 其中Folder一共有三个:Module Folder.Core Fo ...
- Orchard详解--第七篇 拓展模块(译)
Orchard作为一个组件化的CMS,它能够在运行时加载任意模块. Orchard和其它ASP.NET MVC应用一样,支持通过Visual Studio来加载已经编译为程序集的模块,且它还提供了自定 ...
- Orchard详解--第六篇 CacheManager 2
接上一篇,关于ICacheContextAccessor先看一下默认实现,用于保存一个获取上下文,且这个上下文是线程静态的: public class DefaultCacheContextAcces ...
- Orchard详解--第五篇 CacheManager
上一篇文章介绍了Orchard中的缓存,本篇主要针对CacheManager进行分析,CacheManager在Orchard中用于存储应用程序的配置信息以及框架内部的一些功能支持,包括整个拓展及拓展 ...
随机推荐
- python自动化工具之pywinauto(一个实例)结合pyuserinput
以下是pywinauto使用指南.这个窗口句柄可以在Spy++中查看 (Microsoft Spy++(查看窗口句柄) 10.00.30319 官方最新绿色版) python自动化工具之pywinau ...
- 如何正确且高效实现OSSIM中文化的解决方案(图文详解)
前言 对于玩OSSIM的初学者或者中级水平的从业人员来说,都有一定必要性从中文看起,当然,最终还是英文的目标迈进,只是说,为了让自己更快速上手! 虽然系统说明支持中文,实际上,只是台湾的繁体中文而 ...
- 使用docker搭建数据分析环境
注:早在学习<云计算>这门课之前就已经知道docker,学习这门课时老师还鼓励我们自己尝试一下:但是直到去年年底才有机会尝试,用过之后感觉确实很好用.最近需要部署几个shiny应用,又回顾 ...
- “多个单核CPU”与“单个多核CPU”哪种方式性能较强?
多个单核CPU: 成本更高,因为每个CPU都需要一定的线路电路支持,这样对主板上布局布线极为不便.并且当运行多线程任务时,多线程间通信协同合作也是一个问题.依赖总线的传输,速度较慢,且每一个线程因为运 ...
- webpack 配置文件相关解说
博客地址:https://ainyi.com/10 webpack - 什么是webpack: WebPack可以看做是模块打包机:它做的事情是,分析你的项目结构,找到JavaScript模块以及其它 ...
- 20.Module 的语法
Module 的语法 Module 的语法 概述 历史上,JavaScript 一直没有模块(module)体系,无法将一个大程序拆分成互相依赖的小文件,再用简单的方法拼装起来.其他语言都有这项功能, ...
- Opencv-python画图基础知识
相关函数介绍 1. Point 该数据结构表示了由其图像坐标 和 指定的2D点.可定义为: Point pt; pt.x = 10; pt.y = 8; 或者 Point pt = Point(10, ...
- nginx配置反向代理和负载均衡
一.反向代理 说明:应该有一个nginx服务器有多个应用服务器(可以是tomcat),本文使用一台虚拟机,安装一个nginx,多个tomcat,来模拟 upstream tomcats{ server ...
- 我是如何解决java.security.cert.CertPathValidatorException异常的
目录 问题来了 问题分析 解决问题 重新安装服务器端证书 日志带来曙光 刨根到底 总结 附录 tomcat的SSL配置 服务器端证书配置 Keytool命令常用参数 问题来了 昨天,我还在我的工位上愉 ...
- eclipse安装阿里编码规约插件
点击帮助,Install New Software... 地址为https://p3c.alibaba.com/plugin/eclipse/update 然后选择安装, 一路next即可