From a65f57da991d3d566085e056f4e23c3bc2ebc8b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Fri, 3 Nov 2017 17:49:11 +0300 Subject: [PATCH] Resolved #148: Register Controller, PageModel and other MVC components to DI by default. --- .../AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs | 6 +++ .../Volo/Abp/AspNetCore/Mvc/AbpController.cs | 3 +- .../Abp/AspNetCore/Mvc/AbpViewComponent.cs | 3 +- ...tCoreMvcConventionalDependencyRegistrar.cs | 45 +++++++++++++++++++ .../AspNetCore/Mvc/RazorPages/AbpPageModel.cs | 3 +- .../DefaultConventionalRegistrar.cs | 27 ++++++++--- 6 files changed, 75 insertions(+), 12 deletions(-) create mode 100644 src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/DependencyInjection/AbpAspNetCoreMvcConventionalDependencyRegistrar.cs diff --git a/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs index 9b5d38ba79..db0b9123a9 100644 --- a/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs +++ b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs @@ -16,6 +16,7 @@ using Microsoft.AspNetCore.Mvc.Infrastructure; using Microsoft.AspNetCore.Mvc.ViewComponents; using Microsoft.Extensions.DependencyInjection.Extensions; using Volo.Abp.AspNetCore.Mvc.Conventions; +using Volo.Abp.AspNetCore.Mvc.DependencyInjection; using Volo.Abp.AspNetCore.Mvc.VirtualFileSystem; using Volo.Abp.Http; using Volo.Abp.Http.Modeling; @@ -26,6 +27,11 @@ namespace Volo.Abp.AspNetCore.Mvc [DependsOn(typeof(AbpAspNetCoreModule))] public class AbpAspNetCoreMvcModule : AbpModule { + public override void PreConfigureServices(IServiceCollection services) + { + services.AddConventionalRegistrar(new AbpAspNetCoreMvcConventionalRegistrar()); + } + public override void ConfigureServices(IServiceCollection services) { //Configure Razor diff --git a/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpController.cs b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpController.cs index 47901a01c3..3c0ffe9d2f 100644 --- a/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpController.cs +++ b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpController.cs @@ -2,14 +2,13 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; -using Volo.Abp.DependencyInjection; using Volo.Abp.Guids; using Volo.Abp.ObjectMapping; using Volo.Abp.Uow; namespace Volo.Abp.AspNetCore.Mvc { - public abstract class AbpController : Controller, ITransientDependency + public abstract class AbpController : Controller { public IUnitOfWorkManager UnitOfWorkManager { get; set; } diff --git a/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpViewComponent.cs b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpViewComponent.cs index 5696b06501..f66a992df7 100644 --- a/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpViewComponent.cs +++ b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpViewComponent.cs @@ -1,9 +1,8 @@ using Microsoft.AspNetCore.Mvc; -using Volo.Abp.DependencyInjection; namespace Volo.Abp.AspNetCore.Mvc { - public abstract class AbpViewComponent : ViewComponent, ITransientDependency + public abstract class AbpViewComponent : ViewComponent { } } diff --git a/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/DependencyInjection/AbpAspNetCoreMvcConventionalDependencyRegistrar.cs b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/DependencyInjection/AbpAspNetCoreMvcConventionalDependencyRegistrar.cs new file mode 100644 index 0000000000..d49cb6d142 --- /dev/null +++ b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/DependencyInjection/AbpAspNetCoreMvcConventionalDependencyRegistrar.cs @@ -0,0 +1,45 @@ +using System; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.RazorPages; +using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.AspNetCore.Mvc.DependencyInjection +{ + public class AbpAspNetCoreMvcConventionalRegistrar : DefaultConventionalRegistrar + { + protected override ServiceLifetime? GetServiceLifetimeFromClassHierarcy(Type type) + { + var lifeTime = base.GetServiceLifetimeFromClassHierarcy(type); + if (lifeTime != null) + { + return lifeTime; + } + + if (IsController(type) || + IsPageModel(type) || + IsViewComponent(type)) + { + return ServiceLifetime.Transient; + } + + return null; + } + + private static bool IsPageModel(Type type) + { + return typeof(PageModel).IsAssignableFrom(type) || type.IsDefined(typeof(PageModelAttribute), true); + } + + private static bool IsController(Type type) + { + return typeof(Controller).IsAssignableFrom(type) || type.IsDefined(typeof(ControllerAttribute), true); + } + + private static bool IsViewComponent(Type type) + { + return typeof(ViewComponent).IsAssignableFrom(type) || type.IsDefined(typeof(ViewComponentAttribute), true); + } + } +} diff --git a/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/RazorPages/AbpPageModel.cs b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/RazorPages/AbpPageModel.cs index dd27354cd1..eec6fcf081 100644 --- a/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/RazorPages/AbpPageModel.cs +++ b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/RazorPages/AbpPageModel.cs @@ -2,14 +2,13 @@ using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; -using Volo.Abp.DependencyInjection; using Volo.Abp.Guids; using Volo.Abp.ObjectMapping; using Volo.Abp.Uow; namespace Volo.Abp.AspNetCore.Mvc.RazorPages { - public abstract class AbpPageModel : PageModel, ITransientDependency //TODO: Register PageModels by convention, instead of using ITransientDependency + public abstract class AbpPageModel : PageModel { public IUnitOfWorkManager UnitOfWorkManager { get; set; } diff --git a/src/Volo.Abp/Volo/Abp/DependencyInjection/DefaultConventionalRegistrar.cs b/src/Volo.Abp/Volo/Abp/DependencyInjection/DefaultConventionalRegistrar.cs index 9959344f70..19740d6ab6 100644 --- a/src/Volo.Abp/Volo/Abp/DependencyInjection/DefaultConventionalRegistrar.cs +++ b/src/Volo.Abp/Volo/Abp/DependencyInjection/DefaultConventionalRegistrar.cs @@ -1,24 +1,24 @@ using System; using System.Reflection; +using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; namespace Volo.Abp.DependencyInjection { + //TODO: Make DefaultConventionalRegistrar extensible, so we can only define GetLifeTimeOrNull to contribute to the convention. This can be more performant! public class DefaultConventionalRegistrar : ConventionalRegistrarBase { public override void AddType(IServiceCollection services, Type type) { - var typeInfo = type.GetTypeInfo(); - - if (typeInfo.IsDefined(typeof(DisableConventionalRegistrationAttribute), true)) + if (IsConventionalRegistrationDisabled(type)) { return; } - var dependencyAttribute = typeInfo.GetCustomAttribute(true); + var dependencyAttribute = GetDependencyAttributeOrNull(type); + var lifeTime = GetLifeTimeOrNull(type, dependencyAttribute); - var lifeTime = dependencyAttribute?.Lifetime ?? GetServiceLifetimeFromInterfaces(type); if (lifeTime == null) { return; @@ -43,7 +43,22 @@ namespace Volo.Abp.DependencyInjection } } - protected virtual ServiceLifetime? GetServiceLifetimeFromInterfaces(Type type) + protected virtual bool IsConventionalRegistrationDisabled(Type type) + { + return type.IsDefined(typeof(DisableConventionalRegistrationAttribute), true); + } + + protected virtual DependencyAttribute GetDependencyAttributeOrNull(Type type) + { + return type.GetCustomAttribute(true); + } + + protected virtual ServiceLifetime? GetLifeTimeOrNull(Type type, [CanBeNull] DependencyAttribute dependencyAttribute) + { + return dependencyAttribute?.Lifetime ?? GetServiceLifetimeFromClassHierarcy(type); + } + + protected virtual ServiceLifetime? GetServiceLifetimeFromClassHierarcy(Type type) { if (typeof(ITransientDependency).GetTypeInfo().IsAssignableFrom(type)) {