這個問題和我之前關于 Razor Components 的問題類似,但是這個問題是關于 Razor Pages的,它需要不同的截取點。
我正在使用Dependency Injection Principles, Practices, and Patterns (DIPP&P) 一書中解釋的純 DI 方法制作 ASP.NET Core 應用程式。我的應用程式的一部分有一個 Web API 控制器。為了用我的控制器實作Pure DI,我可以輕松地按照 DIPP&P 中的第 7.3.1 節“創建自定義控制器激活器”來創建一個控制器激活器類,類似于 DIPP&P 中的示例。這是通過IControllerActivator在方法中實作和組合我的組合根來完成的create。
我的應用程式還將包含 Razor Pages。我想繼續使用 Pure DI 方法,但我找不到任何有關如何執行此操作的示例。我的假設是我需要創建一個RazorPageActivator類,該類實作IRazorPageActivator并將我的組合根添加到Activate方法中。但是,在查看了RazorPageActivator在 ASP.NET Core GitHub 中找到的類之后,它看起來非常復雜,我擔心如果我通過創建自己的實作IRazorPageActivator事物的類來攔截它(或覆寫它?)會中斷,我會一團糟.
我的問題是,如果可能的話,如何使用 Razor Pages 實作 Pure DI?
uj5u.com熱心網友回復:
使用 Razor Pages,這些IPageModelActivatorProvider功能就像您的 Composition Root 的作曲家。這是一個基于默認 Visual Studio (2019) Razor Pages 專案模板的示例。
讓我們從 custom 開始IPageModelActivatorProvider,它充當您的 Composer,它是您的 Composition Root 的一部分:
public class CommercePageModelActivatorProvider
: IPageModelActivatorProvider, IDisposable
{
// Singletons
private readonly ILoggerFactory loggerFactory;
public CommercePageModelActivatorProvider(ILoggerFactory loggerFactory) =>
this.loggerFactory = loggerFactory;
public Func<PageContext, object> CreateActivator(
CompiledPageActionDescriptor desc) =>
c => this.CreatePageModelType(c, desc.ModelTypeInfo.AsType());
public Action<PageContext, object> CreateReleaser(
CompiledPageActionDescriptor desc) =>
(c, pm) => (pm as IDisposable)?.Dispose();
private object CreatePageModelType(PageContext c, Type pageModelType)
{
// Create Scoped components
var context = new CommerceContext().TrackDisposable(c);
// Create Transient components
switch (pageModelType.Name)
{
case nameof(IndexModel):
return new IndexModel(this.Logger<IndexModel>(), context);
case nameof(PrivacyModel):
return new PrivacyModel(this.Logger<PrivacyModel>());
default: throw new NotImplementedException(pageModelType.FullName);
}
}
public void Dispose() { /* Release Singletons here, if needed */ }
private ILogger<T> Logger<T>() => this.loggerFactory.CreateLogger<T>();
}
請注意此實作的一些事項:
- 這個類的結構與本書代碼示例中給出的非常相似。
- 它實作
IDisposable允許處理自己創建的單例。在這種情況下,它的建構式中沒有創建單例,因此不需要處理任何內容。ILoggerFactory是“外部擁有的” ;它由框架創建,并將由框架處置(如果需要)。 - 該類使用自定義
TrackDisposable擴展方法(稍后顯示),該方法允許跟蹤范圍和瞬態依賴關系。該TrackDisposable方法會將這些實體添加到請求中,并允許框架在請求結束時處理它們。 - 這就是該
CreateReleaser方法僅處理 Page 本身的原因。當您跟蹤它們以進行處置時,框架會完成所有其他已創建組件的處置。您還可以選擇跟蹤頁面本身;在這種情況下,您可以將CreateReleaser委托留空。 - There is a handy
Logger<T>()method that simplifies the creation ofILogger<T>implementations. Those come from the framework and are created by theILoggerFactory.
Here's the TrackDisposable extension method:
public static class DisposableExtensions
{
public static T TrackDisposable<T>(this T instance, PageContext c)
where T : IDisposable
{
c.HttpContext.Response.RegisterForDispose(instance);
return instance;
}
}
The last missing piece of infrastructure required is the registration of your CommercePageModelActivatorProvider into the framework's DI Container. This is done inside the Startup class:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
// Register your custom component activator here
services.AddSingleton<
IPageModelActivatorProvider, CommercePageModelActivatorProvider>();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
...
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/424698.html
