ASP.NET Boilerplate How To Use
Module & Startup Configuration ASP.NET Boilerplate
Overview of Module, Startup Configuration in ASP.NET Boilerplate.
- Module
- Startup Configuration
Module
Introduction:
ASP.NET Boilerplate
cung cấp hạ tầng để xây dựng các module và kết hợp chúng thành một ứng dụng. Một module có thể phụ thuộc vào một hoặc nhiều module khác. Thường thì một assembly
sẽ được coi như một module.
Module Definition:
Một module được định nghĩa là một class được dẫn xuất từ /Abp/Modules/AbpModule
.
public class MyBlogApplicationModule : AbpModule
{
public override void Initialize()
{
IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
}
}
Class
định nghĩa module này có trách nhiệm Register các Class con của nó vào DI Container
thông qua Dependency Injection
. Đoạn code trên thực hiện Register các class của module này theo quy ước (convention). Module này cũng có thể thực hiện configure cho Application, cho các module khác, cho những feature mới của Application…
Module Dependencies
Một module có thể phụ thuộc (dependent) module khác. Bạn cần Explicitly
khai báo sự phụ thuộc này bằng DependsOn
attribute.
[DependsOn(typeof(MyBlogCoreModule))]
public class MyBlogApplicationModule : AbpModule
{
public override void Initialize()
{
IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
}
}
Lifecycle Methods
ASP.NET Boilerplate
sẽ gọi một số hàm cụ thể của module khi Application startup và shutdown. Bạn có thể override
những method này để thực hiện những công việc mong muốn.
ASP.NET Boilerplate
gọi những method này theo thứ tự của dependencies. Ví dụ: nếu module A
phụ thuộc vào module B
, thì module B
sẽ được initialzed trước module A
.
Thứ tự chính xác như sau: PreInitialize-B
, PreInitialize-A
, Initialize-B
, Initialize-A
, PostInitialize-B
và PostInitialize-A
. Quy luật này áp dụng cho toàn bộ dependency graph. Method Shutdown
cũng thực hiện tương tự, nhưng với thứ tự ngược lại.
- PreInitialize: Method này được gọi đầu tiên khi Application start. Nó là một dạng go-to method, gọi ngược ra framework hoặc các module khác để thực hiện một số
Start-Configuration
trước khi nó (module này) được Initialize.
Bạn có thể viết code riêng của mình ở đây, và nó sẽ được thực thi trước DI registration. Ví dụ: nếu bạn tạo một conventional registration class, bạn nên register nó ở đây sử dụngIocManager.AddConventionalRegister
method. - Initialize: Đây là nơi
Dependency Injection Registration
sẽ được thực hiện. Thường dùngIocManager.RegisterAssemblyByConvention
method. Bạn có thể custom lại DI Registration nếu muốn. - PostInitialize: Method này được gọi cuối cùng trong start process. Sẽ an toàn khi resolve (create) một dependency ở đây.
- Shutdown: Method này được gọi khi Application shutdown.
Module Lifetime
Các module class được tự động register là Singleton.
Plugin Modules
Trong khi các module (not Plugin Module) được tìm kiếm và load khi bắt đầu chạy Startup Module và tiến hành load theo các phụ thuộc. Ngoài ra ASP.NET Boilerplate còn có thể load động các module (dynamically
). Class AbpBoostraper
định nghĩa PluginSource
property, thuộc tính này dùng để add plugin source
và load động các plugin module
. Một plugin source
có thể là bất kỳ class nào cài đặt IPluginSource
interface. Class PluginFolderSource
cài đặt interface này để get các plugin module từ các assemblies đặt trong một folder.
ASP.NET Core module của ASP.NET Boilerplate định nghĩa một option trong AddAbp
extension method để add plug sources trong Startup
class.
services.AddAbp<MyStartupModule>(options =>
{
options.PlugInSources.Add(new FolderPlugInSource(@"C:\MyPlugIns"));
});
Chúng ta cũng có thể dùng AddFolder
extension method cho một cú pháp đơn giản hơn
services.AddAbp<MyStartupModule>(options =>
{
options.PlugInSources.AddFolder(@"C:\MyPlugIns");
});
Additional Assemblies
Những implementation mặc định của IAssemblyFinder
và ITypeFinder
, implementation này được ASP.NET Boilerplate
dùng để điều tra các lớp đặc trưng trong ứng dụng (specific class). Tuy nhiên chúng chỉ tìm trong các Module Assembly (AbpModule
), và các Types trong những module đó. Chúng ta có thể override lại method GetAdditionalAssemblies
trong module của mình để include thêm các additional assemblies
.
Custom Module Methods
Module của bạn có thể có những custom method, cái sẽ được dùng bởi những module khác và phụ thuộc vào module này. Giả sử MyModule2
phụ thuộc vào MyModule1
và nó muốn gọi một method của MyModule1
trong PreInitialize
method.
public class MyModule1 : AbpModule
{
public override void Initialize()
{
IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
}
public void MyModuleMethod1()
{
//this is a custom method of this module
}
}
[DependsOn(typeof(MyModule1))]
public class MyModule2 : AbpModule
{
private readonly MyModule1 _myModule1;
public MyModule2(MyModule1 myModule1)
{
_myModule1 = myModule1;
}
public override void PreInitialize()
{
_myModule1.MyModuleMethod1(); //Call MyModule1's method
}
public override void Initialize()
{
IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
}
}
Module Configuration
Trong khi có thể dùng custom method để cấu hình các module, nhưng chúng tôi khuyến nghi bạn sử dụng startup configuration
system để định nghĩa và thiết lập cấu hình cho module.
Startup Configuration
ASP.NET Boilerplate
cung cấp một model để cấu hình các module của nó khi startup.
Việc cấu hình ASP.NET Boilerplate
được tạo bởi PreInitialize
method trong các module cấu thành ứng dụng. Ví dụ:
public class SimpleTaskSystemModule : AbpModule
{
public override void PreInitialize()
{
//Add languages for your application
Configuration.Localization.Languages.Add(new LanguageInfo("en", "English", "famfamfam-flag-england", true));
Configuration.Localization.Languages.Add(new LanguageInfo("tr", "Türkçe", "famfamfam-flag-tr"));
//Add a localization source
Configuration.Localization.Sources.Add(
new XmlLocalizationSource(
"SimpleTaskSystem",
HttpContext.Current.Server.MapPath("~/Localization/SimpleTaskSystem")
)
);
//Configure navigation/menu
Configuration.Navigation.Providers.Add<SimpleTaskSystemNavigationProvider>();
}
public override void Initialize()
{
IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
}
}
ASP.NET Boilerplate
được thiết kế với quan điểm module hoá ứng dụng. Các module khác nhau có thể cấu hình ASP.NET Boilerplate
. Ví dụ, các module khác nhau có thể add navigation provider để add menu item của riêng mình vào main menu. (Tham khảo mục tài liệu Localization
và Navigation
của ASP.NET Boilerplate
).
Replacing Built-In Services
Method Configuration.ReplaceService
có thể được dùng để override một built-in service. Ví dụ, bạn có thể thay thế IAbpSession
service với tuỳ chỉnh cài đặt của bạn như code dưới đây
Configuration.ReplaceService<IAbpSession, MySession>(DependencyLifeStyle.Transient);
Method ReplaceService
còn có một overload có thể truyền một action để tạo một thay thế theo một cách tuỳ biến (bạn có thể dùng trực tiếp Castle Windsor
với tính năng cao cấp registration API).
Cùng một service có thể được thay thế nhiều lần, nhất là trong những module khác nhau. Thằng được thay thế cuối cùng sẽ được sử dụng. Ghi nhớ các PreInitialize
được thực thi theo dependency order.
Configuring Modules
Ngoài bản thân startup configuration
của framework, một module có thể extend IAbpModuleConfiguration
interface để cung cấp configuration points
(nơi để các module khác có thể chọc tới để cấu hình cho module này?). Ví dụ
...
using Abp.Web.Configuration;
...
public override void PreInitialize()
{
Configuration.Modules.AbpWebCommon().SendAllExceptionsToClients = true;
}
...
Trong ví dụ này, chúng ta cấu hình AbpWebCommon
module để send tất cả exception đến client. Ở đây AbpWebCommon
mở ra một configuration point
.
Không phải mọi module cần định nghĩa kiểu cấu hình này. Thường nó sẽ được dùng khi một module có thể được re-use trong những ứng dụng khác nhau và cần được cấu hình cho giai đoạn startup.
Creating Configuration for a Module
Tại sao phải tạo Configuration cho một Module? Sau khi đã mở Configuration Point
giờ chúng ta cần tạo những Configuration Properties
cho module mục tiêu để các module khác có thể thay đổi thông tin cấu hình của module mục tiêu này..
Giả sử chúng ta có một module tên là MyModule
và nó có một vài thuộc tính cấu hình. Đầu tiên, chúng ta tạo một lớp cho những thuộc tính này.
public class MyModuleConfig
{
public bool SampleConfig1 { get; set; }
public string SampleConfig2 { get; set; }
}
Sau đó chúng ta sẽ register class này thông qua Dependency Injection trong method PreInitialize
của MyModule
.
IocManager.Register<MyModuleConfig>();
Nó nên được register là một Singleton
giống như ví dụ này. Như vậy chúng ta đã có thể cấu hình cho MyModule
từ PreInitialize
method của một module khác.
Configuration.Get<MyModuleConfig>().SampleConfig1 = false;
(1) Configuring using extension method
Chúng ta sẽ tạo một extension method cho IModuleConfiguration
, và sử dụng method IAbpStartupConfiguration
như sau
public static class MyModuleConfigurationExtensions
{
public static MyModuleConfig MyModuleConfiguration(this IModuleConfigurations moduleConfigurations)
{
return moduleConfigurations.AbpConfiguration.Get<MyModuleConfig>();
}
}
Và bây giờ dùng extension method trên để configure cho MyModule
.
Configuration.Modules.MyModuleConfiguration().SampleConfig1 = false;
Configuration.Modules.MyModuleConfiguration().SampleConfig2 = "test";
Cách này giúp dễ dàng tập hợp và tìm thông tin cấu hình module tại một điểm (Configuration.Modules…
). ASP.NET Boilerplate
định nghĩa các extension method
cho việc cấu hình các module của nó.
(2) Configuring using injection
Tại một vài chỗ trong MyModule
cần những thông tin cấu hình này. Bạn có thể inject MyModuleConfig
và dùng các configured value. Ví dụ:
public class MyService : ITransientDependency
{
private readonly MyModuleConfig _configuration;
public MyService(MyModuleConfig configuration)
{
_configuration = configuration;
}
public void DoIt()
{
if (_configuration.SampleConfig2 == "test")
{
//...
}
}
}
Conclusion:
Module Definition: class kế thừa AbpModule
Module Dependencies: phải explicitly khai báo bằng DependsOn
annotation.
Module Lifecycle Methods: các method được gọi khi startup application: PreInitialize
, Initialize
, PostInitialize
. Các method được gọi khi shutdown: Shutdown
.
Module Lifetime: Singleton
Plugin Module: dynamically load module
Custom Module Method: method for call by another module.
Startup-configuration: ASP.NET Boilerplate cung cấp model để load cấu hình modules khi startup. Application Configuration là tổng hợp các PreInitialize method của các Module cấu thành.
Replacing Built-in Service: bạn có thể thay thế service của mình thay cho built-in service bằng cách override lại các built-in service này và register nó qua DI.
Configuring Modules: một module có thể mở ra configuration point
để module khác có thể thay đổi cấu hình của nó. Bằng việc sử dụng cấu hình qua extension method đã giúp tập trung thông tin cấu hình tại đơn điểm (Configuration.Modules…), giúp cho việc tìm kiếm và tổng hợp dễ dàng hơn.