本章涉及到的内容如下
1.EngineContext初始化IEngine实例
2.Autofac依赖注入初始化
3.AutoMapper框架初始化
4.启动任务初始化
一.EngineContext初始化
nopCommerce应用启动时首先调用EngineContext.Initialize(false) 进行初始化引擎,
并对IEngine接口进行初始化。IEngine用于实现依赖注入和初始化工作。nop中使用Autofac进行依赖注入。
你会发现nop中很多如:EngineContext.Current.Resolve<ICacheManager>();这样的语句,该Resolve方法用于返回对应接口的实例。
1 [MethodImpl(MethodImplOptions.Synchronized)]//可以确保在不同线程中运行的该方式以同步的方式运行 2 public static IEngine Initialize(bool forceRecreate) 3 { 4 if (Singleton<IEngine>.Instance == null || forceRecreate) 5 { 6 Singleton<IEngine>.Instance = new NopEngine(); 7 8 var config = ConfigurationManager.GetSection("NopConfig") as NopConfig; 9 Singleton<IEngine>.Instance.Initialize(config); 10 } 11 return Singleton<IEngine>.Instance; 12 }
EngineContext.Initialize(false)
二.IEngine接口初始化
NopEngine实现IEngine接口,并在Initialize(NopConfig config)方法中对应用进行初始化工作。
同时使用Resolve方法返回对应接口实例。
首先我们看下Initialize(NopConfig config)方法都做了什么。
1 public void Initialize(NopConfig config) 2 { 3 //register dependencies 注册依赖项 nop 使用 Autofac进行依赖注入 4 RegisterDependencies(config); 5 6 //register mapper configurations 注册对象映射配置 nop 使用 AutoMapper进行对象映射 7 RegisterMapperConfiguration(config); 8 9 //startup tasks 启动任务 10 if (!config.IgnoreStartupTasks) 11 { 12 RunStartupTasks(); 13 } 14 15 }
1.调用RegisterDependencies(config)方法进行依赖注入(IOC)初始化工作
我们先看看代码
1 /// <summary> 2 /// 使用AutoFac注册依赖项 3 /// 遍历所有的实现IDependencyRegistrar接口实例进行注册 4 /// Register dependencies 5 /// </summary> 6 /// <param name="config">Config</param> 7 protected virtual void RegisterDependencies(NopConfig config) 8 { 9 var builder = new ContainerBuilder(); 10 11 //dependencies 12 var typeFinder = new WebAppTypeFinder(); 13 builder.RegisterInstance(config).As<NopConfig>().SingleInstance(); 14 builder.RegisterInstance(this).As<IEngine>().SingleInstance(); 15 builder.RegisterInstance(typeFinder).As<ITypeFinder>().SingleInstance(); 16 17 //register dependencies provided by other assemblies 18 var drTypes = typeFinder.FindClassesOfType<IDependencyRegistrar>(); 19 var drInstances = new List<IDependencyRegistrar>(); 20 foreach (var drType in drTypes) 21 drInstances.Add((IDependencyRegistrar) Activator.CreateInstance(drType)); 22 //sort 23 drInstances = drInstances.AsQueryable().OrderBy(t => t.Order).ToList(); 24 foreach (var dependencyRegistrar in drInstances) 25 dependencyRegistrar.Register(builder, typeFinder, config); 26 27 var container = builder.Build(); 28 this._containerManager = new ContainerManager(container); 29 30 //set dependency resolver 31 DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); 32 }
1.默认使用Autofac依赖注入框架,因此首先创建ioc容器 var builder = new ContainerBuilder();
2.容器中注册NopConfig,IEngine,ITypeFinder。
这里重点说下ITypeFinder接口,该接用于返回程序集,获取某个接口所有实现类。该接口被广泛用在 Nop Engine中。
WebAppTypeFinder类实现了ITypeFinder接口,会获取所有”\bin”目录下*.dll 程序集,并通过反射可以获取到指定接口的实现类。
3.获取所有IDependencyRegistrar接口实现类进行初始化,再调用 Register方法在IOC容器中注册类型及其实例,
最重要的一个实现类就是“Nop.Web.Framework\DependencyRegistrar.cs”,该实现类中将nop所需要的接口实现都注册到ioc容器中。
我们在二次开发中可以创建IDependencyRegistrar的实现类添加自己的业务接口。如何注册大家学习下Autofac框架进一步了解。
下图中列出了nop项目自带的一些IDependencyRegistrar方法。
代码中也可以直接使用 EngineContext.Current.Resolve<“接口”>()进行调用,这种情况常用语视图中。
2.调用RegisterMapperConfiguration(config)方法进行对象映射
还是先看代码
1 /// <summary> 2 /// AutoMapper为对象映射 3 /// 遍历所有的实现IMapperConfiguration接口实例进行注册 4 /// Register mapping 5 /// </summary> 6 /// <param name="config">Config</param> 7 protected virtual void RegisterMapperConfiguration(NopConfig config) 8 { 9 //dependencies 10 var typeFinder = new WebAppTypeFinder(); 11 12 //register mapper configurations provided by other assemblies 13 var mcTypes = typeFinder.FindClassesOfType<IMapperConfiguration>(); 14 var mcInstances = new List<IMapperConfiguration>(); 15 foreach (var mcType in mcTypes) 16 mcInstances.Add((IMapperConfiguration)Activator.CreateInstance(mcType)); 17 //sort 18 mcInstances = mcInstances.AsQueryable().OrderBy(t => t.Order).ToList(); 19 //get configurations 20 var configurationActions = new List<Action<IMapperConfigurationExpression>>(); 21 foreach (var mc in mcInstances) 22 configurationActions.Add(mc.GetConfiguration()); 23 //register 24 AutoMapperConfiguration.Init(configurationActions); 25 }
使用AutoMapper框架进行对象映射,简单些就是Dto与Model之间的转换.
这里同样使用ITypeFinder 获取所有IMapperConfiguration的实现类,并在实现类中完成Dto与Model之间的映射关系。
同样如果自行扩展IMapperConfiguration的实现类,nop在此也会自动进行配置的。
nop中只在Nop.Admin项目中使用AutoMapper进行对象映射。
而Nop.Web项目并没有使用AutoMapper而是用扩展来实现的。
3.运行启动任务
最后说下应用启动时运行启动任务
在配置类NopConfig中IgnoreStartupTasks来控制是否启动
1 /// <summary> 2 /// 启动时运行的任务任务 3 /// 遍历所有实现IStartupTask接口的实例 4 /// Run startup tasks 5 /// </summary> 6 protected virtual void RunStartupTasks() 7 { 8 var typeFinder = _containerManager.Resolve<ITypeFinder>(); 9 var startUpTaskTypes = typeFinder.FindClassesOfType<IStartupTask>(); 10 var startUpTasks = new List<IStartupTask>(); 11 foreach (var startUpTaskType in startUpTaskTypes) 12 startUpTasks.Add((IStartupTask)Activator.CreateInstance(startUpTaskType)); 13 //sort 14 startUpTasks = startUpTasks.AsQueryable().OrderBy(st => st.Order).ToList(); 15 foreach (var startUpTask in startUpTasks) 16 startUpTask.Execute(); 17 }
同样使用ITypeFinder 来获取所有 IStartupTask接口的实现类,并调用Execute()方法来执行。
三.总结:
NopEngine实现nop引擎,并通过Autofac,AutoMapper对nop进行初始化。
ITypeFinder 接口很重要,因为nop扩展功能都依赖于它来实现。nop有很好的接口截止,大家进行二次开发的时候进行接口实现就可以了,nop会自动进行初始化配置。
如果Autofac,AutoMapper中的配置不好理解可以留言一起讨论学习。