diff --git a/Volo.Abp.sln b/Volo.Abp.sln index 0a6c02672c..adab6a5b0c 100644 --- a/Volo.Abp.sln +++ b/Volo.Abp.sln @@ -108,6 +108,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Identity.HttpApi.C EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Autofac", "src\Volo.Abp.Autofac\Volo.Abp.Autofac.csproj", "{CECE1288-B5A1-4A6B-BEE0-331861F94983}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Castle.Core", "src\Volo.Abp.Castle.Core\Volo.Abp.Castle.Core.csproj", "{053F7446-0545-482E-9F29-9C96B926966C}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -258,6 +260,10 @@ Global {CECE1288-B5A1-4A6B-BEE0-331861F94983}.Debug|Any CPU.Build.0 = Debug|Any CPU {CECE1288-B5A1-4A6B-BEE0-331861F94983}.Release|Any CPU.ActiveCfg = Release|Any CPU {CECE1288-B5A1-4A6B-BEE0-331861F94983}.Release|Any CPU.Build.0 = Release|Any CPU + {053F7446-0545-482E-9F29-9C96B926966C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {053F7446-0545-482E-9F29-9C96B926966C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {053F7446-0545-482E-9F29-9C96B926966C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {053F7446-0545-482E-9F29-9C96B926966C}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -308,5 +314,6 @@ Global {17B14A48-5248-4F4C-A8E6-6926AA94EB7C} = {1895A5C9-50D4-4568-9A3A-14657E615A5E} {00B240B6-EC44-461A-9578-EF4F1BE9C688} = {1895A5C9-50D4-4568-9A3A-14657E615A5E} {CECE1288-B5A1-4A6B-BEE0-331861F94983} = {4C753F64-0C93-4D65-96C2-A40893AFC1E8} + {053F7446-0545-482E-9F29-9C96B926966C} = {4C753F64-0C93-4D65-96C2-A40893AFC1E8} EndGlobalSection EndGlobal diff --git a/src/AbpDesk/AbpDesk.ConsoleDemo/AbpDesk/ConsoleDemo/Program.cs b/src/AbpDesk/AbpDesk.ConsoleDemo/AbpDesk/ConsoleDemo/Program.cs index 13d3465558..fd661d9277 100644 --- a/src/AbpDesk/AbpDesk.ConsoleDemo/AbpDesk/ConsoleDemo/Program.cs +++ b/src/AbpDesk/AbpDesk.ConsoleDemo/AbpDesk/ConsoleDemo/Program.cs @@ -48,7 +48,7 @@ namespace AbpDesk.ConsoleDemo { application .ServiceProvider - .GetRequiredService() + .GetRequiredService() .List(); application diff --git a/src/AbpDesk/AbpDesk.ConsoleDemo/AbpDesk/ConsoleDemo/TicketLister.cs b/src/AbpDesk/AbpDesk.ConsoleDemo/AbpDesk/ConsoleDemo/TicketLister.cs index c9ec569632..125d732a53 100644 --- a/src/AbpDesk/AbpDesk.ConsoleDemo/AbpDesk/ConsoleDemo/TicketLister.cs +++ b/src/AbpDesk/AbpDesk.ConsoleDemo/AbpDesk/ConsoleDemo/TicketLister.cs @@ -28,4 +28,28 @@ namespace AbpDesk.ConsoleDemo } } } + + //Uses TicketAppService instead of ITicketAppService. + public class TicketLister2 : ITransientDependency + { + private readonly TicketAppService _ticketAppService; + + public TicketLister2(TicketAppService ticketAppService) + { + _ticketAppService = ticketAppService; + } + + public void List() + { + Console.WriteLine(); + Console.WriteLine("List of tickets:"); + + var result = AsyncHelper.RunSync(() => _ticketAppService.GetAll(new GetAllTicketsInput())); + + foreach (var ticket in result.Items) + { + Console.WriteLine(ticket); + } + } + } } \ No newline at end of file diff --git a/src/Volo.Abp.Autofac/Volo.Abp.Autofac.csproj b/src/Volo.Abp.Autofac/Volo.Abp.Autofac.csproj index a40ff12745..233560f871 100644 --- a/src/Volo.Abp.Autofac/Volo.Abp.Autofac.csproj +++ b/src/Volo.Abp.Autofac/Volo.Abp.Autofac.csproj @@ -18,6 +18,7 @@ + diff --git a/src/Volo.Abp.Autofac/Volo/Abp/Autofac/AbpAutofacServiceProviderFactory.cs b/src/Volo.Abp.Autofac/Volo/Abp/Autofac/AbpAutofacServiceProviderFactory.cs index 3165c690ff..59502fb2ac 100644 --- a/src/Volo.Abp.Autofac/Volo/Abp/Autofac/AbpAutofacServiceProviderFactory.cs +++ b/src/Volo.Abp.Autofac/Volo/Abp/Autofac/AbpAutofacServiceProviderFactory.cs @@ -1,7 +1,13 @@ using System; +using System.Linq; +using System.Reflection; using Autofac; +using Autofac.Core; using Autofac.Extensions.DependencyInjection; +using Castle.DynamicProxy; using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Castle.DynamicProxy; +using Volo.Abp.DynamicProxy; namespace Volo.Abp.Autofac { @@ -11,6 +17,7 @@ namespace Volo.Abp.Autofac public class AbpAutofacServiceProviderFactory : IServiceProviderFactory { private readonly ContainerBuilder _builder; + private IServiceCollection _services; public AbpAutofacServiceProviderFactory(ContainerBuilder builder) { @@ -24,7 +31,9 @@ namespace Volo.Abp.Autofac /// A container builder that can be used to create an . public ContainerBuilder CreateBuilder(IServiceCollection services) { - AutofacRegistration.Populate(_builder, services); + _services = services; + + _builder.Populate(services); return _builder; } @@ -33,7 +42,91 @@ namespace Volo.Abp.Autofac { Check.NotNull(containerBuilder, nameof(containerBuilder)); + HandleRegistrationActions(containerBuilder); + return new AutofacServiceProvider(containerBuilder.Build()); } + + private static readonly ProxyGenerator _proxyGenerator = new ProxyGenerator(); + + private void HandleRegistrationActions(ContainerBuilder containerBuilder) + { + var registrationActions = _services.GetServiceRegistrationActionList(); + containerBuilder.RegisterCallback(registry => + { + foreach (var registration in registry.Registrations) + { + var registredArgs = new OnServiceRegistredArgs(registration.Activator.LimitType); + + foreach (var registrationAction in registrationActions) + { + registrationAction(registredArgs); + } + + registration.Preparing += (sender, args) => + { + + }; + + registration.Activating += (sender, args) => + { + if (args.Component.Services.OfType().Any(swt => !swt.ServiceType.GetTypeInfo().IsVisible) || args.Instance.GetType().Namespace.StartsWith("Castle.Proxies")) + { + return; + } + + if (registredArgs.Interceptors.Any()) + { + ApplyInterceptors(args, registredArgs); + } + }; + } + }); + } + + private static void ApplyInterceptors(ActivatingEventArgs args, OnServiceRegistredArgs registredArgs) + { + var mainService = args.Component.Services.OfType().FirstOrDefault()?.ServiceType; + if (mainService == null) + { + return; + } + + var interceptorInstances = registredArgs.Interceptors + .Select(i => (IInterceptor)new CastleAbpInterceptorAdapter((IAbpInterceptor)args.Context.Resolve(i))) + .ToArray(); + + if (mainService.GetTypeInfo().IsInterface) + { + args.ReplaceInstance( + _proxyGenerator + .CreateInterfaceProxyWithTargetInterface( + mainService, + args.Instance, + interceptorInstances + ) + ); + } + else + { + //var proxied = _proxyGenerator + // .CreateClassProxyWithTarget( + // mainService, + // args.Instance, + // interceptorInstances + // ); + + //args.ReplaceInstance(proxied); + + //args.ReplaceInstance( + // _proxyGenerator + // .CreateClassProxyWithTarget( + // mainService, + // args.Instance, + // interceptorInstances + // ) + //); + } + } } } \ No newline at end of file diff --git a/src/Volo.Abp.Castle.Core/Volo.Abp.Castle.Core.csproj b/src/Volo.Abp.Castle.Core/Volo.Abp.Castle.Core.csproj new file mode 100644 index 0000000000..0aac971cac --- /dev/null +++ b/src/Volo.Abp.Castle.Core/Volo.Abp.Castle.Core.csproj @@ -0,0 +1,23 @@ + + + + netstandard1.6 + Volo.Abp.Castle.Core + Volo.Abp.Castle.Core + 1.6.1 + $(PackageTargetFallback);dnxcore50 + false + false + false + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpInterceptorAdapter.cs b/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpInterceptorAdapter.cs new file mode 100644 index 0000000000..8a999d3433 --- /dev/null +++ b/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpInterceptorAdapter.cs @@ -0,0 +1,20 @@ +using Castle.DynamicProxy; +using Volo.Abp.DynamicProxy; + +namespace Volo.Abp.Castle.DynamicProxy +{ + public class CastleAbpInterceptorAdapter : IInterceptor + { + private readonly IAbpInterceptor _abpInterceptor; + + public CastleAbpInterceptorAdapter(IAbpInterceptor abpInterceptor) + { + _abpInterceptor = abpInterceptor; + } + + public void Intercept(IInvocation invocation) + { + _abpInterceptor.Intercept(new CastleAbpMethodInvocationAdapter(invocation)); + } + } +} diff --git a/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpMethodInvocationAdapter.cs b/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpMethodInvocationAdapter.cs new file mode 100644 index 0000000000..ee9c0dba69 --- /dev/null +++ b/src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpMethodInvocationAdapter.cs @@ -0,0 +1,36 @@ +using System; +using System.Reflection; +using Castle.DynamicProxy; +using Volo.Abp.DynamicProxy; + +namespace Volo.Abp.Castle.DynamicProxy +{ + public class CastleAbpMethodInvocationAdapter : IAbpMethodInvocation + { + public object[] Arguments => _invocation.Arguments; + + public Type[] GenericArguments => _invocation.GenericArguments; + + public object TargetObject => _invocation.InvocationTarget; + + public MethodInfo Method => _invocation.MethodInvocationTarget; + + public object ReturnValue + { + get => _invocation.ReturnValue; + set => _invocation.ReturnValue = value; + } + + private readonly IInvocation _invocation; + + public CastleAbpMethodInvocationAdapter(IInvocation invocation) + { + _invocation = invocation; + } + + public void Proceed() + { + _invocation.Proceed(); + } + } +} \ No newline at end of file diff --git a/src/Volo.Abp/Microsoft/Extensions/DependencyInjection/IOnServiceRegistredArgs.cs b/src/Volo.Abp/Microsoft/Extensions/DependencyInjection/IOnServiceRegistredArgs.cs new file mode 100644 index 0000000000..9ec89ea509 --- /dev/null +++ b/src/Volo.Abp/Microsoft/Extensions/DependencyInjection/IOnServiceRegistredArgs.cs @@ -0,0 +1,13 @@ +using System; +using Volo.Abp.Collections; +using Volo.Abp.DynamicProxy; + +namespace Microsoft.Extensions.DependencyInjection +{ + public interface IOnServiceRegistredArgs + { + ITypeList Interceptors { get; } + + Type ImplementationType { get; } + } +} \ No newline at end of file diff --git a/src/Volo.Abp/Microsoft/Extensions/DependencyInjection/OnServiceRegistredArgs.cs b/src/Volo.Abp/Microsoft/Extensions/DependencyInjection/OnServiceRegistredArgs.cs new file mode 100644 index 0000000000..eb241be871 --- /dev/null +++ b/src/Volo.Abp/Microsoft/Extensions/DependencyInjection/OnServiceRegistredArgs.cs @@ -0,0 +1,21 @@ +using System; +using Volo; +using Volo.Abp.Collections; +using Volo.Abp.DynamicProxy; + +namespace Microsoft.Extensions.DependencyInjection +{ + public class OnServiceRegistredArgs : IOnServiceRegistredArgs + { + public virtual ITypeList Interceptors { get; } + + public virtual Type ImplementationType { get; } + + public OnServiceRegistredArgs(Type implementationType) + { + ImplementationType = Check.NotNull(implementationType, nameof(implementationType)); + + Interceptors = new TypeList(); + } + } +} \ No newline at end of file diff --git a/src/Volo.Abp/Microsoft/Extensions/DependencyInjection/ServiceCollectionConventionalRegistrationExtensions.cs b/src/Volo.Abp/Microsoft/Extensions/DependencyInjection/ServiceCollectionConventionalRegistrationExtensions.cs index 5cf620e8c6..c06bed4236 100644 --- a/src/Volo.Abp/Microsoft/Extensions/DependencyInjection/ServiceCollectionConventionalRegistrationExtensions.cs +++ b/src/Volo.Abp/Microsoft/Extensions/DependencyInjection/ServiceCollectionConventionalRegistrationExtensions.cs @@ -18,7 +18,7 @@ namespace Microsoft.Extensions.DependencyInjection return GetOrCreateRegistrarList(services); } - private static List GetOrCreateRegistrarList(IServiceCollection services) + private static ConventionalRegistrarList GetOrCreateRegistrarList(IServiceCollection services) { var conventionalRegistrars = services.GetSingletonInstanceOrNull>()?.Value; if (conventionalRegistrars == null) diff --git a/src/Volo.Abp/Microsoft/Extensions/DependencyInjection/ServiceCollectionRegistrationActionExtensions.cs b/src/Volo.Abp/Microsoft/Extensions/DependencyInjection/ServiceCollectionRegistrationActionExtensions.cs new file mode 100644 index 0000000000..63e8764ee4 --- /dev/null +++ b/src/Volo.Abp/Microsoft/Extensions/DependencyInjection/ServiceCollectionRegistrationActionExtensions.cs @@ -0,0 +1,30 @@ +using System; +using Volo.DependencyInjection; + +namespace Microsoft.Extensions.DependencyInjection +{ + public static class ServiceCollectionRegistrationActionExtensions + { + public static void OnServiceRegistred(this IServiceCollection services, Action registrationAction) + { + GetOrCreateServiceActionList(services).Add(registrationAction); + } + + public static ServiceRegistrationActionList GetServiceRegistrationActionList(this IServiceCollection services) + { + return GetOrCreateServiceActionList(services); + } + + private static ServiceRegistrationActionList GetOrCreateServiceActionList(IServiceCollection services) + { + var registrationActionList = services.GetSingletonInstanceOrNull>()?.Value; + if (registrationActionList == null) + { + registrationActionList = new ServiceRegistrationActionList(); + services.AddObjectAccessor(registrationActionList); + } + + return registrationActionList; + } + } +} diff --git a/src/Volo.Abp/Volo/Abp/AbpKernelModule.cs b/src/Volo.Abp/Volo/Abp/AbpKernelModule.cs index 4568163806..a242ac516d 100644 --- a/src/Volo.Abp/Volo/Abp/AbpKernelModule.cs +++ b/src/Volo.Abp/Volo/Abp/AbpKernelModule.cs @@ -1,12 +1,21 @@ using System; +using System.Reflection; using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Application.Services; +using Volo.Abp.Domain.Repositories; using Volo.Abp.Modularity; +using Volo.Abp.Uow; using Volo.DependencyInjection; namespace Volo.Abp { public class AbpKernelModule : AbpModule { + public override void PreConfigureServices(IServiceCollection services) + { + services.OnServiceRegistred(registration => { RegisterUnitOfWorkInterceptor(registration); }); + } + public override void ConfigureServices(IServiceCollection services) { services.AddOptions(); @@ -21,5 +30,13 @@ namespace Volo.Abp { context.ServiceProvider.GetRequiredService>().Value = context.ServiceProvider; } + + private static void RegisterUnitOfWorkInterceptor(IOnServiceRegistredArgs registration) + { + if (typeof(IApplicationService).GetTypeInfo().IsAssignableFrom(registration.ImplementationType)) + { + registration.Interceptors.Add(); + } + } } } diff --git a/src/Volo.Abp/Volo/Abp/DynamicProxy/IAbpMethodInvocation.cs b/src/Volo.Abp/Volo/Abp/DynamicProxy/IAbpMethodInvocation.cs index 4ea6c67f5a..41a842ee6c 100644 --- a/src/Volo.Abp/Volo/Abp/DynamicProxy/IAbpMethodInvocation.cs +++ b/src/Volo.Abp/Volo/Abp/DynamicProxy/IAbpMethodInvocation.cs @@ -9,9 +9,9 @@ namespace Volo.Abp.DynamicProxy Type[] GenericArguments { get; } - object InvocationTarget { get; } + object TargetObject { get; } - MethodInfo MethodInvocationTarget { get; } + MethodInfo Method { get; } object ReturnValue { get; set; } diff --git a/src/Volo.Abp/Volo/Abp/Uow/UnitOfWorkInterceptor.cs b/src/Volo.Abp/Volo/Abp/Uow/UnitOfWorkInterceptor.cs new file mode 100644 index 0000000000..3382047296 --- /dev/null +++ b/src/Volo.Abp/Volo/Abp/Uow/UnitOfWorkInterceptor.cs @@ -0,0 +1,13 @@ +using Volo.Abp.DynamicProxy; +using Volo.DependencyInjection; + +namespace Volo.Abp.Uow +{ + public class UnitOfWorkInterceptor : IAbpInterceptor, ITransientDependency + { + public void Intercept(IAbpMethodInvocation invocation) + { + invocation.Proceed(); + } + } +} diff --git a/src/Volo.Abp/Volo/DependencyInjection/AutoRegistrationHelper.cs b/src/Volo.Abp/Volo/DependencyInjection/AutoRegistrationHelper.cs index 45bb82f6be..ed279475fd 100644 --- a/src/Volo.Abp/Volo/DependencyInjection/AutoRegistrationHelper.cs +++ b/src/Volo.Abp/Volo/DependencyInjection/AutoRegistrationHelper.cs @@ -26,15 +26,19 @@ namespace Volo.DependencyInjection return GetDefaultExposedServices(type); } - public static IEnumerable GetDefaultExposedServices(Type type) + public static IEnumerable GetDefaultExposedServices(Type type, bool includeSelf = true) { - var typeInfo = type.GetTypeInfo(); + var serviceTypes = new List(); - var serviceTypes = new List { type }; + if (includeSelf) + { + serviceTypes.Add(type); + } - foreach (var interfaceType in typeInfo.GetInterfaces()) + foreach (var interfaceType in type.GetTypeInfo().GetInterfaces()) { var interfaceName = interfaceType.Name; + if (interfaceName.StartsWith("I")) { interfaceName = interfaceName.Right(interfaceName.Length - 1); diff --git a/src/Volo.Abp/Volo/DependencyInjection/ServiceRegistrationActionList.cs b/src/Volo.Abp/Volo/DependencyInjection/ServiceRegistrationActionList.cs new file mode 100644 index 0000000000..beac0e8069 --- /dev/null +++ b/src/Volo.Abp/Volo/DependencyInjection/ServiceRegistrationActionList.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using Microsoft.Extensions.DependencyInjection; + +namespace Volo.DependencyInjection +{ + public class ServiceRegistrationActionList : List> + { + + } +} \ No newline at end of file