我的NopCommerce之旅(4): 依赖注入(IOC/DI)
一、基础介绍
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的结构分析
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 }

浙公网安备 33010602011771号