-
Notifications
You must be signed in to change notification settings - Fork 324
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add interceptor and dynamicProxy support for LightInject (#151)
- Loading branch information
1 parent
f6b67cf
commit 5138fe4
Showing
10 changed files
with
624 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
19 changes: 19 additions & 0 deletions
19
extras/src/AspectCore.Extensions.LightInject/AspectCore.Extensions.LightInject.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<Import Project="..\..\..\build\common.props" /> | ||
|
||
<PropertyGroup> | ||
<Description>Interceptor and dynamicProxy support for LightInject via AspectCore Framework.</Description> | ||
<PackageTags>DynamicProxy;Aop;LightInject;AspectCore</PackageTags> | ||
<PackageReleaseNotes>Interceptor and dynamicProxy support for LightInject via AspectCore Framework.</PackageReleaseNotes> | ||
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> | ||
<TargetFramework>netstandard2.0</TargetFramework> | ||
</PropertyGroup> | ||
<ItemGroup> | ||
<PackageReference Include="LightInject" Version="5.4.0" /> | ||
</ItemGroup> | ||
<ItemGroup> | ||
<ProjectReference Include="..\..\..\core\src\AspectCore.Core\AspectCore.Core.csproj" /> | ||
</ItemGroup> | ||
</Project> | ||
|
158 changes: 158 additions & 0 deletions
158
extras/src/AspectCore.Extensions.LightInject/ContainerBuilderExtensions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Reflection; | ||
using System.Text; | ||
using AspectCore.Configuration; | ||
using AspectCore.DynamicProxy; | ||
using AspectCore.DynamicProxy.Parameters; | ||
using AspectCore.Injector; | ||
using LightInject; | ||
using IServiceContainer = LightInject.IServiceContainer; | ||
|
||
namespace AspectCore.Extensions.LightInject | ||
{ | ||
public enum RegistryType | ||
{ | ||
ByType, | ||
ByInstance, | ||
ByFactory | ||
} | ||
|
||
public static class ContainerBuilderExtensions | ||
{ | ||
private static readonly string[] _nonAspect = | ||
{ | ||
"LightInject.*", | ||
"LightInject" | ||
}; | ||
|
||
private static readonly string[] _excepts = new[] | ||
{ | ||
"Microsoft.Extensions.Logging", | ||
"Microsoft.Extensions.Options", | ||
"System", | ||
"System.*", | ||
"IHttpContextAccessor", | ||
"ITelemetryInitializer", | ||
"IHostingEnvironment", | ||
}.Concat(_nonAspect).ToArray(); | ||
|
||
public static IServiceContainer RegisterDynamicProxy(this IServiceContainer container, | ||
IAspectConfiguration aspectConfig = null, | ||
Action<IAspectConfiguration> configure = null) | ||
{ | ||
if (container == null) | ||
{ | ||
throw new ArgumentNullException(nameof(container)); | ||
} | ||
aspectConfig = aspectConfig ?? new AspectConfiguration(); | ||
|
||
foreach (var m in _nonAspect) | ||
{ | ||
aspectConfig.NonAspectPredicates.AddNamespace(m); | ||
} | ||
|
||
configure?.Invoke(aspectConfig); | ||
|
||
container.RegisterInstance<IAspectConfiguration>(aspectConfig) | ||
.Register(typeof(IManyEnumerable<>), typeof(ManyEnumerable<>)) | ||
.RegisterInstance<IServiceContainer>(container) | ||
.Register<IServiceProvider, LightInjectServiceResolver>() | ||
.Register<IServiceResolver, LightInjectServiceResolver>() | ||
.Register<IAspectContextFactory, AspectContextFactory>() | ||
.Register<IAspectActivatorFactory, AspectActivatorFactory>() | ||
.Register<IProxyGenerator, ProxyGenerator>() | ||
.Register<IParameterInterceptorSelector, ParameterInterceptorSelector>() | ||
.Register<IPropertyInjectorFactory, PropertyInjectorFactory>() | ||
.Register<IInterceptorCollector, InterceptorCollector>() | ||
.Register<IInterceptorSelector, ConfigureInterceptorSelector>() | ||
.Register<IInterceptorSelector, AttributeInterceptorSelector>() | ||
.Register<IAdditionalInterceptorSelector, AttributeAdditionalInterceptorSelector>() | ||
.Register<IAspectValidatorBuilder, AspectValidatorBuilder>() | ||
.Register<IAspectBuilderFactory, AspectBuilderFactory>() | ||
.Register<IProxyTypeGenerator, ProxyTypeGenerator>() | ||
.Register<IAspectCachingProvider, AspectCachingProvider>() | ||
.Register<IAspectExceptionWrapper, AspectExceptionWrapper>(); | ||
|
||
container.Decorate(aspectConfig.CreateDecorator()); | ||
|
||
return container; | ||
} | ||
|
||
private static RegistryType GetRegistryType(this ServiceRegistration registration) | ||
{ | ||
if (registration.FactoryExpression != null) return RegistryType.ByFactory; | ||
else if (registration.Value != null) return RegistryType.ByInstance; | ||
else return RegistryType.ByType; | ||
} | ||
|
||
private static Type GetImplType(this ServiceRegistration registration) | ||
{ | ||
switch (registration.GetRegistryType()) | ||
{ | ||
case RegistryType.ByType: return registration.ImplementingType; | ||
case RegistryType.ByInstance: return registration.Value.GetType(); | ||
case RegistryType.ByFactory: return registration.FactoryExpression.Method.ReturnType; | ||
default: throw new ArgumentOutOfRangeException(); | ||
} | ||
} | ||
|
||
private static DecoratorRegistration CreateDecorator(this IAspectConfiguration aspectConfiguration) | ||
{ | ||
var reg = new DecoratorRegistration() | ||
{ | ||
CanDecorate = s => CanDecorate(s, aspectConfiguration), | ||
ImplementingTypeFactory = CreateProxyType | ||
}; | ||
return reg; | ||
} | ||
|
||
private static Type CreateProxyType(IServiceFactory factory, ServiceRegistration registration) | ||
{ | ||
var serviceType = registration.ServiceType.GetTypeInfo(); | ||
var implType = registration.GetImplType(); | ||
var proxyTypeGenerator = factory.GetInstance<IProxyTypeGenerator>(); | ||
|
||
if (serviceType.IsClass) | ||
{ | ||
return proxyTypeGenerator.CreateClassProxyType(serviceType, implType); | ||
} | ||
else if (serviceType.IsGenericTypeDefinition) | ||
{ | ||
return proxyTypeGenerator.CreateClassProxyType(implType, implType); | ||
} | ||
else | ||
{ | ||
return proxyTypeGenerator.CreateInterfaceProxyType(serviceType, implType); | ||
} | ||
} | ||
|
||
private static bool CanDecorate(ServiceRegistration registration, IAspectConfiguration aspectConfiguration) | ||
{ | ||
var serviceType = registration.ServiceType.GetTypeInfo(); | ||
var implType = registration.GetImplType().GetTypeInfo(); | ||
|
||
if (implType.IsProxy() || !implType.CanInherited()) | ||
{ | ||
return false; | ||
} | ||
if (_excepts.Any(x => implType.Name.Matches(x)) || _excepts.Any(x => implType.Namespace.Matches(x))) | ||
{ | ||
return false; | ||
} | ||
if (!serviceType.CanInherited() || serviceType.IsNonAspect()) | ||
{ | ||
return false; | ||
} | ||
|
||
var aspectValidator = new AspectValidatorBuilder(aspectConfiguration).Build(); | ||
if (!aspectValidator.Validate(serviceType, true) && !aspectValidator.Validate(implType, false)) | ||
{ | ||
return false; | ||
} | ||
return true; | ||
} | ||
|
||
} | ||
} |
36 changes: 36 additions & 0 deletions
36
extras/src/AspectCore.Extensions.LightInject/LightInjectServiceResolver.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Text; | ||
using AspectCore.DynamicProxy; | ||
using AspectCore.Injector; | ||
using LightInject; | ||
using IServiceContainer = LightInject.IServiceContainer; | ||
|
||
namespace AspectCore.Extensions.LightInject | ||
{ | ||
[NonAspect] | ||
internal class LightInjectServiceResolver : IServiceResolver | ||
{ | ||
private readonly IServiceContainer _container; | ||
|
||
public LightInjectServiceResolver(IServiceContainer container) | ||
{ | ||
_container = container; | ||
} | ||
|
||
public object GetService(Type serviceType) | ||
{ | ||
return _container.TryGetInstance(serviceType); | ||
} | ||
|
||
public void Dispose() | ||
{ | ||
_container.Dispose(); | ||
} | ||
|
||
public object Resolve(Type serviceType) | ||
{ | ||
return _container.TryGetInstance(serviceType); | ||
} | ||
} | ||
} |
22 changes: 22 additions & 0 deletions
22
...test/AspectCore.Extensions.LightInject.Test/AspectCore.Extensions.LightInject.Test.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>netcoreapp2.0</TargetFramework> | ||
<DebugType>portable</DebugType> | ||
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles> | ||
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> | ||
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> | ||
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" /> | ||
<PackageReference Include="xunit" Version="2.4.1" /> | ||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\..\src\AspectCore.Extensions.LightInject\AspectCore.Extensions.LightInject.csproj" /> | ||
</ItemGroup> | ||
|
||
</Project> |
31 changes: 31 additions & 0 deletions
31
extras/test/AspectCore.Extensions.LightInject.Test/AsyncIncreamentAttribute.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
using System; | ||
using System.Threading.Tasks; | ||
using AspectCore.DynamicProxy; | ||
|
||
namespace AspectCoreTest.LightInject | ||
{ | ||
[AttributeUsage(AttributeTargets.Method)] | ||
public class AsyncIncreamentAttribute : AbstractInterceptorAttribute | ||
{ | ||
public override async Task Invoke(AspectContext context, AspectDelegate next) | ||
{ | ||
await context.Invoke(next); | ||
await Task.Delay(100); // 此处模拟一个真.异步方法,用于测试线程上下文切换 | ||
|
||
if (context.ReturnValue is Task<int> task) | ||
{ | ||
var result = await task; | ||
context.ReturnValue = Task.FromResult(result + 1); | ||
} | ||
else if (context.ReturnValue is ValueTask<int> valueTask) | ||
{ | ||
var result = await valueTask; | ||
context.ReturnValue = new ValueTask<int>(result + 1); | ||
} | ||
else if (context.ReturnValue is int result) | ||
{ | ||
context.ReturnValue = result + 1; | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.