我的NopCommerce之旅(4): 依赖注入(IOC/DI)

一、基础介绍

依赖注入,Dependency Injection,权威解释及说明请自己查阅资料。
这里简单说一下常见使用:在mvc的controller的构造方法中定义参数,如ICountryService countryService,然后直接使用countryService(构造注入)。
复制代码
 1         public CountryController(ICountryService countryService, 
 2             IStateProvinceService stateProvinceService, 
 3             ILocalizationService localizationService, 
 4             IWorkContext workContext,
 5             ICacheManager cacheManager)
 6         {
 7             this._countryService = countryService;
 8             this._stateProvinceService = stateProvinceService;
 9             this._localizationService = localizationService;
10             this._workContext = workContext;
11             this._cacheManager = cacheManager;
12         }
复制代码

显然,你并没有在controller调用前,new一个ICountryService的对象给controller做参数,你也不知道该在哪去写这个调用。没关系,这些都交给系统处理,你不必理会,这就是依赖注入。

二、承上启下

上一篇大致分析了应用启动,而NopCommerce完成注册依赖就在初始化上下文部分。通过代码跟踪,即可发现Nop.Core.Infrastructure.NopEngine.RegisterDependencies()。

1             //initialize engine context 初始化上下文
2             EngineContext.Initialize(false);
复制代码
 1         /// <summary>
 2         /// Initializes a static instance of the Nop factory.
 3         /// </summary>
 4         /// <param name="forceRecreate">Creates a new factory instance even though the factory has been previously initialized.</param>
 5         [MethodImpl(MethodImplOptions.Synchronized)]
 6         public static IEngine Initialize(bool forceRecreate)
 7         {
 8             if (Singleton<IEngine>.Instance == null || forceRecreate)
 9             {
10                 Singleton<IEngine>.Instance = new NopEngine();
11 
12                 var config = ConfigurationManager.GetSection("NopConfig") as NopConfig;
13                 Singleton<IEngine>.Instance.Initialize(config);
14             }
15             return Singleton<IEngine>.Instance;
16         }
复制代码
复制代码
 1         /// <summary>
 2         /// Initialize components and plugins in the nop environment.
 3         /// </summary>
 4         /// <param name="config">Config</param>
 5         public void Initialize(NopConfig config)
 6         {
 7             //register dependencies
 8             RegisterDependencies(config);
 9 
10             //startup tasks
11             if (!config.IgnoreStartupTasks)
12             {
13                 RunStartupTasks();
14             }
15 
16         }
复制代码
复制代码
 1         /// <summary>
 2         /// Register dependencies
 3         /// </summary>
 4         /// <param name="config">Config</param>
 5         protected virtual void RegisterDependencies(NopConfig config)
 6         {
 7             var builder = new ContainerBuilder();
 8             var container = builder.Build();
 9             this._containerManager = new ContainerManager(container);
10 
11             //we create new instance of ContainerBuilder
12             //because Build() or Update() method can only be called once on a ContainerBuilder.
13 
14             //dependencies
15             var typeFinder = new WebAppTypeFinder();
16             builder = new ContainerBuilder();
17             builder.RegisterInstance(config).As<NopConfig>().SingleInstance();
18             builder.RegisterInstance(this).As<IEngine>().SingleInstance();
19             builder.RegisterInstance(typeFinder).As<ITypeFinder>().SingleInstance();
20             builder.Update(container);
21 
22             //register dependencies provided by other assemblies
23             builder = new ContainerBuilder();
24             var drTypes = typeFinder.FindClassesOfType<IDependencyRegistrar>();
25             var drInstances = new List<IDependencyRegistrar>();
26             foreach (var drType in drTypes)
27                 drInstances.Add((IDependencyRegistrar) Activator.CreateInstance(drType));
28             //sort
29             drInstances = drInstances.AsQueryable().OrderBy(t => t.Order).ToList();
30             foreach (var dependencyRegistrar in drInstances)
31                 dependencyRegistrar.Register(builder, typeFinder, config);通过反射,按顺序注册依赖
32             builder.Update(container);
33 
34             //set dependency resolver
35             DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
36         }
复制代码

三、NopCommerce的结构分析

  本文通过从依赖注入框架Autofac的DependencyRegistrar方法来分析NopCommerce的结构。

1.分析方法

  在vs里Solution Explorer的查找栏输入DependencyRegistrar,即可看到所有实现DependencyRegistrar()方法的。

  2.总结

    2.1 Nop.Core定义了接口;

    2.2 Plugins注册自己需要的类;

    2.3 Nop.Admin和Nop.Web注册Controller所要使用的缓存类;

    2.4 Nop.Web.Framework注册了NopCommerce的核心类。

四、代码分析

  1.这里主要分析Nop.Web.Framework的DependencyRegistrar()

  1.1.注册http上下文;

  1.2.注册web helper、user agent helper;

  1.3.注册mvc的controllers;

  1.4.注册数据层类,如dbcontext,manager,repository,供持久化层的操作;

  1.5.注册插件plugins;

  1.6.注册缓存管理的相关类;

  1.7.注册work context和store context;

  1.8.注册业务层services,部分需注册缓存参数,可以看到WithParameter( ResolvedParameter.ForNamed< ICacheManager >("nop_cache_static" ));

  1.9.注册用户事件。

2.代码如下

复制代码
  1         /// <summary>
  2         /// Register services and interfaces
  3         /// </summary>
  4         /// <param name="builder">Container builder</param>
  5         /// <param name="typeFinder">Type finder</param>
  6         /// <param name="config">Config</param>
  7         public virtual void Register(ContainerBuilder builder, ITypeFinder typeFinder, NopConfig config)
  8         {
  9             //HTTP context and other related stuff
 10             builder.Register(c => 
 11                 //register FakeHttpContext when HttpContext is not available
 12                 HttpContext.Current != null ?
 13                 (new HttpContextWrapper(HttpContext.Current) as HttpContextBase) :
 14                 (new FakeHttpContext("~/") as HttpContextBase))
 15                 .As<HttpContextBase>()
 16                 .InstancePerLifetimeScope();
 17             builder.Register(c => c.Resolve<HttpContextBase>().Request)
 18                 .As<HttpRequestBase>()
 19                 .InstancePerLifetimeScope();
 20             builder.Register(c => c.Resolve<HttpContextBase>().Response)
 21                 .As<HttpResponseBase>()
 22                 .InstancePerLifetimeScope();
 23             builder.Register(c => c.Resolve<HttpContextBase>().Server)
 24                 .As<HttpServerUtilityBase>()
 25                 .InstancePerLifetimeScope();
 26             builder.Register(c => c.Resolve<HttpContextBase>().Session)
 27                 .As<HttpSessionStateBase>()
 28                 .InstancePerLifetimeScope();
 29 
 30             //web helper
 31             builder.RegisterType<WebHelper>().As<IWebHelper>().InstancePerLifetimeScope();
 32             //user agent helper
 33             builder.RegisterType<UserAgentHelper>().As<IUserAgentHelper>().InstancePerLifetimeScope();
 34 
 35             
 36             //controllers
 37             builder.RegisterControllers(typeFinder.GetAssemblies().ToArray());
 38 
 39             //data layer
 40             var dataSettingsManager = new DataSettingsManager();
 41             var dataProviderSettings = dataSettingsManager.LoadSettings();
 42             builder.Register(c => dataSettingsManager.LoadSettings()).As<DataSettings>();
 43             builder.Register(x => new EfDataProviderManager(x.Resolve<DataSettings>())).As<BaseDataProviderManager>().InstancePerDependency();
 44 
 45 
 46             builder.Register(x => x.Resolve<BaseDataProviderManager>().LoadDataProvider()).As<IDataProvider>().InstancePerDependency();
 47 
 48             if (dataProviderSettings != null && dataProviderSettings.IsValid())
 49             {
 50                 var efDataProviderManager = new EfDataProviderManager(dataSettingsManager.LoadSettings());
 51                 var dataProvider = efDataProviderManager.LoadDataProvider();
 52                 dataProvider.InitConnectionFactory();
 53 
 54                 builder.Register<IDbContext>(c => new NopObjectContext(dataProviderSettings.DataConnectionString)).InstancePerLifetimeScope();
 55             }
 56             else
 57             {
 58                 builder.Register<IDbContext>(c => new NopObjectContext(dataSettingsManager.LoadSettings().DataConnectionString)).InstancePerLifetimeScope();
 59             }
 60 
 61 
 62             builder.RegisterGeneric(typeof(EfRepository<>)).As(typeof(IRepository<>)).InstancePerLifetimeScope();
 63             
 64             //plugins
 65             builder.RegisterType<PluginFinder>().As<IPluginFinder>().InstancePerLifetimeScope();
 66             builder.RegisterType<OfficialFeedManager>().As<IOfficialFeedManager>().InstancePerLifetimeScope();
 67 
 68             //cache managers
 69             if (config.RedisCachingEnabled)
 70             {
 71                 builder.RegisterType<RedisCacheManager>().As<ICacheManager>().Named<ICacheManager>("nop_cache_static").InstancePerLifetimeScope();
 72             }
 73             else
 74             {
 75                 builder.RegisterType<MemoryCacheManager>().As<ICacheManager>().Named<ICacheManager>("nop_cache_static").SingleInstance();
 76             }
 77             builder.RegisterType<PerRequestCacheManager>().As<ICacheManager>().Named<ICacheManager>("nop_cache_per_request").InstancePerLifetimeScope();
 78 
 79             if (config.RunOnAzureWebsites)
 80             {
 81                 builder.RegisterType<AzureWebsitesMachineNameProvider>().As<IMachineNameProvider>().SingleInstance();
 82             }
 83             else
 84             {
 85                 builder.RegisterType<DefaultMachineNameProvider>().As<IMachineNameProvider>().SingleInstance();
 86             }
 87 
 88             //work context
 89             builder.RegisterType<WebWorkContext>().As<IWorkContext>().InstancePerLifetimeScope();
 90             //store context
 91             builder.RegisterType<WebStoreContext>().As<IStoreContext>().InstancePerLifetimeScope();
 92 
 93             //services
 94             builder.RegisterType<BackInStockSubscriptionService>().As<IBackInStockSubscriptionService>().InstancePerLifetimeScope();
 95             builder.RegisterType<CategoryService>().As<ICategoryService>().InstancePerLifetimeScope();
 96             builder.RegisterType<CompareProductsService>().As<ICompareProductsService>().InstancePerLifetimeScope();
 97             builder.RegisterType<RecentlyViewedProductsService>().As<IRecentlyViewedProductsService>().InstancePerLifetimeScope();
 98             builder.RegisterType<ManufacturerService>().As<IManufacturerService>().InstancePerLifetimeScope();
 99             builder.RegisterType<PriceFormatter>().As<IPriceFormatter>().InstancePerLifetimeScope();
100             builder.RegisterType<ProductAttributeFormatter>().As<IProductAttributeFormatter>().InstancePerLifetimeScope();
101             builder.RegisterType<ProductAttributeParser>().As<IProductAttributeParser>().InstancePerLifetimeScope();
102             builder.RegisterType<ProductAttributeService>().As<IProductAttributeService>().InstancePerLifetimeScope();
103             builder.RegisterType<ProductService>().As<IProductService>().InstancePerLifetimeScope();
104             builder.RegisterType<CopyProductService>().As<ICopyProductService>().InstancePerLifetimeScope();
105             builder.RegisterType<SpecificationAttributeService>().As<ISpecificationAttributeService>().InstancePerLifetimeScope();
106             builder.RegisterType<ProductTemplateService>().As<IProductTemplateService>().InstancePerLifetimeScope();
107             builder.RegisterType<CategoryTemplateService>().As<ICategoryTemplateService>().InstancePerLifetimeScope();
108             builder.RegisterType<ManufacturerTemplateService>().As<IManufacturerTemplateService>().InstancePerLifetimeScope();
109             builder.RegisterType<TopicTemplateService>().As<ITopicTemplateService>().InstancePerLifetimeScope();
110             //use static cache (between HTTP requests)
111             builder.RegisterType<ProductTagService>().As<IProductTagService>()
112                 .WithParameter(ResolvedParameter.ForNamed<ICacheManager>("nop_cache_static"))
113                 .InstancePerLifetimeScope();
114 
115             builder.RegisterType<AddressAttributeFormatter>().As<IAddressAttributeFormatter>().InstancePerLifetimeScope();
116             builder.RegisterType<AddressAttributeParser>().As<IAddressAttributeParser>().InstancePerLifetimeScope();
117             builder.RegisterType<AddressAttributeService>().As<IAddressAttributeService>().InstancePerLifetimeScope();
118             builder.RegisterType<AddressService>().As<IAddressService>().InstancePerLifetimeScope();
119             builder.RegisterType<AffiliateService>().As<IAffiliateService>().InstancePerLifetimeScope();
120             builder.RegisterType<VendorService>().As<IVendorService>().InstancePerLifetimeScope();
121             builder.RegisterType<SearchTermService>().As<ISearchTermService>().InstancePerLifetimeScope();
122             builder.RegisterType<GenericAttributeService>().As<IGenericAttributeService>().InstancePerLifetimeScope();
123             builder.RegisterType<FulltextService>().As<IFulltextService>().InstancePerLifetimeScope();
124             builder.RegisterType<MaintenanceService>().As<IMaintenanceService>().InstancePerLifetimeScope();
125 
126 
127             builder.RegisterType<CustomerAttributeParser>().As<ICustomerAttributeParser>().InstancePerLifetimeScope();
128             builder.RegisterType<CustomerAttributeService>().As<ICustomerAttributeService>().InstancePerLifetimeScope();
129             builder.RegisterType<CustomerService>().As<ICustomerService>().InstancePerLifetimeScope();
130             builder.RegisterType<CustomerRegistrationService>().As<ICustomerRegistrationService>().InstancePerLifetimeScope();
131             builder.RegisterType<CustomerReportService>().As<ICustomerReportService>().InstancePerLifetimeScope();
132 
133             //use static cache (between HTTP requests)
134             builder.RegisterType<PermissionService>().As<IPermissionService>()
135                 .WithParameter(ResolvedParameter.ForNamed<ICacheManager>("nop_cache_static"))
136                 .InstancePerLifetimeScope();
137             //use static cache (between HTTP requests)
138             builder.RegisterType<AclService>().As<IAclService>()
139                 .WithParameter(ResolvedParameter.ForNamed<ICacheManager>("nop_cache_static"))
140                 .InstancePerLifetimeScope();
141             //use static cache (between HTTP requests)
142             builder.RegisterType<PriceCalculationService>().As<IPriceCalculationService>()
143                 .WithParameter(ResolvedParameter.ForNamed<ICacheManager>("nop_cache_static"))
144                 .InstancePerLifetimeScope();
145 
146             builder.RegisterType<GeoLookupService>().As<IGeoLookupService>().InstancePerLifetimeScope();
147             builder.RegisterType<CountryService>().As<ICountryService>().InstancePerLifetimeScope();
148             builder.RegisterType<CurrencyService>().As<ICurrencyService>().InstancePerLifetimeScope();
149             builder.RegisterType<MeasureService>().As<IMeasureService>().InstancePerLifetimeScope();
150             builder.RegisterType<StateProvinceService>().As<IStateProvinceService>().InstancePerLifetimeScope();
151 
152             builder.RegisterType<StoreService>().As<IStoreService>().InstancePerLifetimeScope();
153             //use static cache (between HTTP requests)
154             builder.RegisterType<StoreMappingService>().As<IStoreMappingService>()
155                 .WithParameter(ResolvedParameter.ForNamed<ICacheManager>("nop_cache_static"))
156                 .InstancePerLifetimeScope();
157 
158             builder.RegisterType<DiscountService>().As<IDiscountService>().InstancePerLifetimeScope();
159 
160 
161             //use static cache (between HTTP requests)
162             builder.RegisterType<SettingService>().As<ISettingService>()
163                 .WithParameter(ResolvedParameter.ForNamed<ICacheManager>("nop_cache_static"))
164                 .InstancePerLifetimeScope();
165             builder.RegisterSource(new SettingsSource());
166 
167             //use static cache (between HTTP requests)
168             builder.RegisterType<LocalizationService>().As<ILocalizationService>()
169                 .WithParameter(ResolvedParameter.ForNamed<ICacheManager>("nop_cache_static"))
170                 .InstancePerLifetimeScope();
171 
172             //use static cache (between HTTP requests)
173             builder.RegisterType<LocalizedEntityService>().As<ILocalizedEntityService>()
174                 .WithParameter(ResolvedParameter.ForNamed<ICacheManager>("nop_cache_static"))
175                 .InstancePerLifetimeScope();
176             builder.RegisterType<LanguageService>().As<ILanguageService>().InstancePerLifetimeScope();
177 
178             builder.RegisterType<DownloadService>().As<IDownloadService>().InstancePerLifetimeScope();
179             //picture service
180             var useAzureBlobStorage = !String.IsNullOrEmpty(config.AzureBlobStorageConnectionString);
181             if (useAzureBlobStorage)
182             {
183                 //Windows Azure BLOB
184                 builder.RegisterType<AzurePictureService>().As<IPictureService>().InstancePerLifetimeScope();
185             }
186             else
187             {
188                 //standard file system
189                 builder.RegisterType<PictureService>().As<IPictureService>().InstancePerLifetimeScope();
190             }
191 
192             builder.RegisterType<MessageTemplateService>().As<IMessageTemplateService>().InstancePerLifetimeScope();
193             builder.RegisterType<QueuedEmailService>().As<IQueuedEmailService>().InstancePerLifetimeScope();
194             builder.RegisterType<NewsLetterSubscriptionService>().As<INewsLetterSubscriptionService>().InstancePerLifetimeScope();
195             builder.RegisterType<CampaignService>().As<ICampaignService>().InstancePerLifetimeScope();
196             builder.RegisterType<EmailAccountService>().As<IEmailAccountService>().InstancePerLifetimeScope();
197             builder.RegisterType<WorkflowMessageService>().As<IWorkflowMessageService>().InstancePerLifetimeScope();
198             builder.RegisterType<MessageTokenProvider>().As<IMessageTokenProvider>().InstancePerLifetimeScope();
199             builder.RegisterType<Tokenizer>().As<ITokenizer>().InstancePerLifetimeScope();
200             builder.RegisterType<EmailSender>().As<IEmailSender>().InstancePerLifetimeScope();
201 
202             builder.RegisterType<CheckoutAttributeFormatter>().As<ICheckoutAttributeFormatter>().InstancePerLifetimeScope();
203             builder.RegisterType<CheckoutAttributeParser>().As<ICheckoutAttributeParser>().InstancePerLifetimeScope();
204             builder.RegisterType<CheckoutAttributeService>().As<ICheckoutAttributeService>().InstancePerLifetimeScope();
205             builder.RegisterType<GiftCardService>().As<IGiftCardService>().InstancePerLifetimeScope();
206             builder.RegisterType<OrderService>().As<IOrderService>().InstancePerLifetimeScope();
207             builder.RegisterType<OrderReportService>().As<IOrderReportService>().InstancePerLifetimeScope();
208             builder.RegisterType<OrderProcessingService>().As<IOrderProcessingService>().InstancePerLifetimeScope();
209             builder.RegisterType<OrderTotalCalculationService>().As<IOrderTotalCalculationService>().InstancePerLifetimeScope();
210             builder.RegisterType<ReturnRequestService>().As<IReturnRequestService>().InstancePerLifetimeScope();
211             builder.RegisterType<RewardPointService>().As<IRewardPointService>().InstancePerLifetimeScope();
212             builder.RegisterType<ShoppingCartService>().As<IShoppingCartService>().InstancePerLifetimeScope();
213 
214             builder.RegisterType<PaymentService>().As<IPaymentService>().InstancePerLifetimeScope();
215 
216             builder.RegisterType<EncryptionService>().As<IEncryptionService>().InstancePerLifetimeScope();
217             builder.RegisterType<FormsAuthenticationService>().As<IAuthenticationService>().InstancePerLifetimeScope();
218 
219 
220             //use static cache (between HTTP requests)
221             builder.RegisterType<UrlRecordService>().As<IUrlRecordService>()
222                 .WithParameter(ResolvedParameter.ForNamed<ICacheManager>("nop_cache_static"))
223                 .InstancePerLifetimeScope();
224 
225             builder.RegisterType<ShipmentService>().As<IShipmentService>().InstancePerLifetimeScope();
226             builder.RegisterType<ShippingService>().As<IShippingService>().InstancePerLifetimeScope();
227 
228             builder.RegisterType<TaxCategoryService>().As<ITaxCategoryService>().InstancePerLifetimeScope();
229             builder.RegisterType<TaxService>().As<ITaxService>().InstancePerLifetimeScope();
230 
231             builder.RegisterType<DefaultLogger>().As<ILogger>().InstancePerLifetimeScope();
232 
233             //use static cache (between HTTP requests)
234             builder.RegisterType<CustomerActivityService>().As<ICustomerActivityService>()
235                 .WithParameter(ResolvedParameter.ForNamed<ICacheManager>("nop_cache_static"))
236                 .InstancePerLifetimeScope();
237 
238             bool databaseInstalled = DataSettingsHelper.DatabaseIsInstalled();
239             if (!databaseInstalled)
240             {
241                 //installation service
242                 if (config.UseFastInstallationService)
243                 {
244                     builder.RegisterType<SqlFileInstallationService>().As<IInstallationService>().InstancePerLifetimeScope();
245                 }
246                 else
247                 {
248                     builder.RegisterType<CodeFirstInstallationService>().As<IInstallationService>().InstancePerLifetimeScope();
249                 }
250             }
251 
252             builder.RegisterType<ForumService>().As<IForumService>().InstancePerLifetimeScope();
253 
254             builder.RegisterType<PollService>().As<IPollService>().InstancePerLifetimeScope();
255             builder.RegisterType<BlogService>().As<IBlogService>().InstancePerLifetimeScope();
256             builder.RegisterType<WidgetService>().As<IWidgetService>().InstancePerLifetimeScope();
257             builder.RegisterType<TopicService>().As<ITopicService>().InstancePerLifetimeScope();
258             builder.RegisterType<NewsService>().As<INewsService>().InstancePerLifetimeScope();
259 
260             builder.RegisterType<DateTimeHelper>().As<IDateTimeHelper>().InstancePerLifetimeScope();
261             builder.RegisterType<SitemapGenerator>().As<ISitemapGenerator>().InstancePerLifetimeScope();
262             builder.RegisterType<PageHeadBuilder>().As<IPageHeadBuilder>().InstancePerLifetimeScope();
263 
264             builder.RegisterType<ScheduleTaskService>().As<IScheduleTaskService>().InstancePerLifetimeScope();
265 
266             builder.RegisterType<ExportManager>().As<IExportManager>().InstancePerLifetimeScope();
267             builder.RegisterType<ImportManager>().As<IImportManager>().InstancePerLifetimeScope();
268             builder.RegisterType<PdfService>().As<IPdfService>().InstancePerLifetimeScope();
269             builder.RegisterType<ThemeProvider>().As<IThemeProvider>().InstancePerLifetimeScope();
270             builder.RegisterType<ThemeContext>().As<IThemeContext>().InstancePerLifetimeScope();
271 
272 
273             builder.RegisterType<ExternalAuthorizer>().As<IExternalAuthorizer>().InstancePerLifetimeScope();
274             builder.RegisterType<OpenAuthenticationService>().As<IOpenAuthenticationService>().InstancePerLifetimeScope();
275            
276                 
277             builder.RegisterType<RoutePublisher>().As<IRoutePublisher>().SingleInstance();
278 
279             //Register event consumers
280             var consumers = typeFinder.FindClassesOfType(typeof(IConsumer<>)).ToList();
281             foreach (var consumer in consumers)
282             {
283                 builder.RegisterType(consumer)
284                     .As(consumer.FindInterfaces((type, criteria) =>
285                     {
286                         var isMatch = type.IsGenericType && ((Type)criteria).IsAssignableFrom(type.GetGenericTypeDefinition());
287                         return isMatch;
288                     }, typeof(IConsumer<>)))
289                     .InstancePerLifetimeScope();
290             }
291             builder.RegisterType<EventPublisher>().As<IEventPublisher>().SingleInstance();
292             builder.RegisterType<SubscriptionService>().As<ISubscriptionService>().SingleInstance();
293 
294         }
复制代码

posted on 2023-03-11 22:26  大西瓜3721  阅读(38)  评论(0编辑  收藏  举报

导航