From 95ec06303735514457e0dfe34e568cc69b0a80e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Sun, 10 Sep 2017 16:43:03 +0300 Subject: [PATCH] Created some helper extension methods for IServiceCollection. Also made AbpAppServiceConvention replaceable. --- .../AspNetCore/Mvc/AbpAppServiceConvention.cs | 51 +++++------ .../Mvc/AbpAppServiceConventionWrapper.cs | 23 +++++ .../AspNetCore/Mvc/AbpMvcOptionsExtensions.cs | 2 +- .../Mvc/IAbpAppServiceConvention.cs | 8 ++ .../ServiceCollectionCommonExtensions.cs | 88 ++++++++++++++++++- src/Volo.Abp/Properties/AssemblyInfo.cs | 1 + 6 files changed, 142 insertions(+), 31 deletions(-) create mode 100644 src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAppServiceConventionWrapper.cs create mode 100644 src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/IAbpAppServiceConvention.cs diff --git a/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAppServiceConvention.cs b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAppServiceConvention.cs index eb0ed9ae91..2077f275b4 100644 --- a/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAppServiceConvention.cs +++ b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAppServiceConvention.cs @@ -7,28 +7,21 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.ApplicationModels; using Microsoft.AspNetCore.Mvc.Internal; using Microsoft.AspNetCore.Mvc.ModelBinding; -using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Volo.Abp.Application.Services; +using Volo.Abp.DependencyInjection; using Volo.Abp.Http; using Volo.Abp.Reflection; namespace Volo.Abp.AspNetCore.Mvc { - public class AbpAppServiceConvention : IApplicationModelConvention + public class AbpAppServiceConvention : IAbpAppServiceConvention, ITransientDependency { - private readonly Lazy _configuration; + private readonly AbpAspNetCoreMvcOptions _options; - public AbpAppServiceConvention(IServiceCollection services) + public AbpAppServiceConvention(IOptions options) { - _configuration = new Lazy(() => - { - return services - .GetSingletonInstance() - .ServiceProvider - .GetRequiredService>() - .Value; - }, true); + _options = options.Value; } public void Apply(ApplicationModel application) @@ -57,7 +50,7 @@ namespace Volo.Abp.AspNetCore.Mvc } } - private void ConfigureArea(ControllerModel controller, [CanBeNull] AbpControllerAssemblySetting configuration) + protected virtual void ConfigureArea(ControllerModel controller, [CanBeNull] AbpControllerAssemblySetting configuration) { if (configuration == null) { @@ -72,14 +65,14 @@ namespace Volo.Abp.AspNetCore.Mvc controller.RouteValues["area"] = configuration.ModuleName; } - private void ConfigureRemoteService(ControllerModel controller, [CanBeNull] AbpControllerAssemblySetting configuration) + protected virtual void ConfigureRemoteService(ControllerModel controller, [CanBeNull] AbpControllerAssemblySetting configuration) { ConfigureApiExplorer(controller); ConfigureSelector(controller, configuration); ConfigureParameters(controller); } - private void ConfigureParameters(ControllerModel controller) + protected virtual void ConfigureParameters(ControllerModel controller) { foreach (var action in controller.Actions) { @@ -101,9 +94,9 @@ namespace Volo.Abp.AspNetCore.Mvc } } - private bool CanUseFormBodyBinding(ActionModel action, ParameterModel parameter) + protected virtual bool CanUseFormBodyBinding(ActionModel action, ParameterModel parameter) { - if (_configuration.Value.FormBodyBindingIgnoredTypes.Any(t => t.IsAssignableFrom(parameter.ParameterInfo.ParameterType))) + if (_options.FormBodyBindingIgnoredTypes.Any(t => t.IsAssignableFrom(parameter.ParameterInfo.ParameterType))) { return false; } @@ -133,7 +126,7 @@ namespace Volo.Abp.AspNetCore.Mvc return true; } - private void ConfigureApiExplorer(ControllerModel controller) + protected virtual void ConfigureApiExplorer(ControllerModel controller) { if (controller.ApiExplorer.GroupName.IsNullOrEmpty()) { @@ -162,7 +155,7 @@ namespace Volo.Abp.AspNetCore.Mvc } } - private void ConfigureApiExplorer(ActionModel action) + protected virtual void ConfigureApiExplorer(ActionModel action) { if (action.ApiExplorer.IsVisible == null) { @@ -176,7 +169,7 @@ namespace Volo.Abp.AspNetCore.Mvc } } - private void ConfigureSelector(ControllerModel controller, [CanBeNull] AbpControllerAssemblySetting configuration) + protected virtual void ConfigureSelector(ControllerModel controller, [CanBeNull] AbpControllerAssemblySetting configuration) { RemoveEmptySelectors(controller.Selectors); @@ -193,7 +186,7 @@ namespace Volo.Abp.AspNetCore.Mvc } } - private void ConfigureSelector(string moduleName, string controllerName, ActionModel action, [CanBeNull] AbpControllerAssemblySetting configuration) + protected virtual void ConfigureSelector(string moduleName, string controllerName, ActionModel action, [CanBeNull] AbpControllerAssemblySetting configuration) { RemoveEmptySelectors(action.Selectors); @@ -207,7 +200,7 @@ namespace Volo.Abp.AspNetCore.Mvc } } - private void AddAbpServiceSelector(string moduleName, string controllerName, ActionModel action, [CanBeNull] AbpControllerAssemblySetting configuration) + protected virtual void AddAbpServiceSelector(string moduleName, string controllerName, ActionModel action, [CanBeNull] AbpControllerAssemblySetting configuration) { var verb = configuration?.UseConventionalHttpVerbs == true ? HttpVerbHelper.GetConventionalVerbForMethodName(action.ActionName) @@ -222,7 +215,7 @@ namespace Volo.Abp.AspNetCore.Mvc action.Selectors.Add(abpServiceSelectorModel); } - private static void NormalizeSelectorRoutes(string moduleName, string controllerName, ActionModel action) + protected virtual void NormalizeSelectorRoutes(string moduleName, string controllerName, ActionModel action) { foreach (var selector in action.Selectors) { @@ -235,25 +228,25 @@ namespace Volo.Abp.AspNetCore.Mvc } } - private string GetModuleNameOrDefault(Type controllerType) + protected virtual string GetModuleNameOrDefault(Type controllerType) { return GetControllerSettingOrNull(controllerType)?.ModuleName ?? AbpControllerAssemblySetting.DefaultServiceModuleName; } [CanBeNull] - private AbpControllerAssemblySetting GetControllerSettingOrNull(Type controllerType) + protected virtual AbpControllerAssemblySetting GetControllerSettingOrNull(Type controllerType) { - return _configuration.Value.ControllerAssemblySettings.GetSettingOrNull(controllerType); + return _options.ControllerAssemblySettings.GetSettingOrNull(controllerType); } - private static AttributeRouteModel CreateAbpServiceAttributeRouteModel(string moduleName, string controllerName, ActionModel action, string verb) + protected virtual AttributeRouteModel CreateAbpServiceAttributeRouteModel(string moduleName, string controllerName, ActionModel action, string verb) { var url = $"api/services/{moduleName}/{controllerName}/{action.ActionName}"; return new AttributeRouteModel(new RouteAttribute(url)); } - private static void RemoveEmptySelectors(IList selectors) + protected virtual void RemoveEmptySelectors(IList selectors) { selectors .Where(IsEmptySelector) @@ -261,7 +254,7 @@ namespace Volo.Abp.AspNetCore.Mvc .ForEach(s => selectors.Remove(s)); } - private static bool IsEmptySelector(SelectorModel selector) + protected virtual bool IsEmptySelector(SelectorModel selector) { return selector.AttributeRouteModel == null && selector.ActionConstraints.IsNullOrEmpty(); } diff --git a/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAppServiceConventionWrapper.cs b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAppServiceConventionWrapper.cs new file mode 100644 index 0000000000..c4fff972b6 --- /dev/null +++ b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAppServiceConventionWrapper.cs @@ -0,0 +1,23 @@ +using System; +using Microsoft.AspNetCore.Mvc.ApplicationModels; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.AspNetCore.Mvc +{ + [DisableConventionalRegistration] + public class AbpAppServiceConventionWrapper : IApplicationModelConvention + { + private readonly Lazy _convention; + + public AbpAppServiceConventionWrapper(IServiceCollection services) + { + _convention = services.GetRequiredServiceLazy(); + } + + public void Apply(ApplicationModel application) + { + _convention.Value.Apply(application); + } + } +} \ No newline at end of file diff --git a/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpMvcOptionsExtensions.cs b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpMvcOptionsExtensions.cs index 5b3b1fcd75..9b9a85f4cc 100644 --- a/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpMvcOptionsExtensions.cs +++ b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpMvcOptionsExtensions.cs @@ -14,7 +14,7 @@ namespace Volo.Abp.AspNetCore.Mvc private static void AddConventions(MvcOptions options, IServiceCollection services) { - options.Conventions.Add(new AbpAppServiceConvention(services)); + options.Conventions.Add(new AbpAppServiceConventionWrapper(services)); } private static void AddFilters(MvcOptions options) diff --git a/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/IAbpAppServiceConvention.cs b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/IAbpAppServiceConvention.cs new file mode 100644 index 0000000000..899d66b4c2 --- /dev/null +++ b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/IAbpAppServiceConvention.cs @@ -0,0 +1,8 @@ +using Microsoft.AspNetCore.Mvc.ApplicationModels; + +namespace Volo.Abp.AspNetCore.Mvc +{ + public interface IAbpAppServiceConvention : IApplicationModelConvention + { + } +} \ No newline at end of file diff --git a/src/Volo.Abp/Microsoft/Extensions/DependencyInjection/ServiceCollectionCommonExtensions.cs b/src/Volo.Abp/Microsoft/Extensions/DependencyInjection/ServiceCollectionCommonExtensions.cs index 5f04dcab2c..36188d5422 100644 --- a/src/Volo.Abp/Microsoft/Extensions/DependencyInjection/ServiceCollectionCommonExtensions.cs +++ b/src/Volo.Abp/Microsoft/Extensions/DependencyInjection/ServiceCollectionCommonExtensions.cs @@ -69,5 +69,91 @@ namespace Microsoft.Extensions.DependencyInjection builderAction?.Invoke(builder); return serviceProviderFactory.CreateServiceProvider(builder); } - } + + /// + /// Resolves a dependency using given . + /// This method should be used only after dependency injection registration phase completed. + /// + internal static T GetService(this IServiceCollection services) + { + return services + .GetSingletonInstance() + .ServiceProvider + .GetService(); + } + + /// + /// Resolves a dependency using given . + /// This method should be used only after dependency injection registration phase completed. + /// + internal static object GetService(this IServiceCollection services, Type type) + { + return services + .GetSingletonInstance() + .ServiceProvider + .GetService(type); + } + + /// + /// Resolves a dependency using given . + /// Throws exception if service is not registered. + /// This method should be used only after dependency injection registration phase completed. + /// + internal static T GetRequiredService(this IServiceCollection services) + { + return services + .GetSingletonInstance() + .ServiceProvider + .GetRequiredService(); + } + + /// + /// Resolves a dependency using given . + /// Throws exception if service is not registered. + /// This method should be used only after dependency injection registration phase completed. + /// + internal static object GetRequiredService(this IServiceCollection services, Type type) + { + return services + .GetSingletonInstance() + .ServiceProvider + .GetRequiredService(type); + } + + /// + /// Returns a to resolve a service from given + /// once dependency injection registration phase completed. + /// + internal static Lazy GetServiceLazy(this IServiceCollection services) + { + return new Lazy(services.GetService, true); + } + + /// + /// Returns a to resolve a service from given + /// once dependency injection registration phase completed. + /// + internal static Lazy GetServiceLazy(this IServiceCollection services, Type type) + { + return new Lazy(() => services.GetService(type), true); + } + + /// + /// Returns a to resolve a service from given + /// once dependency injection registration phase completed. + /// + internal static Lazy GetRequiredServiceLazy(this IServiceCollection services) + { + return new Lazy(services.GetRequiredService, true); + } + + /// + /// Returns a to resolve a service from given + /// once dependency injection registration phase completed. + /// + internal static Lazy GetRequiredServiceLazy(this IServiceCollection services, Type type) + { + return new Lazy(() => services.GetRequiredService(type), true); + } + } } \ No newline at end of file diff --git a/src/Volo.Abp/Properties/AssemblyInfo.cs b/src/Volo.Abp/Properties/AssemblyInfo.cs index b1dd0ae8b9..ceda416b42 100644 --- a/src/Volo.Abp/Properties/AssemblyInfo.cs +++ b/src/Volo.Abp/Properties/AssemblyInfo.cs @@ -11,6 +11,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyTrademark("")] [assembly: InternalsVisibleTo("Volo.Abp.Tests")] +[assembly: InternalsVisibleTo("Volo.Abp.AspNetCore.Mvc")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from