Browse Source

Created BuildServiceProviderFromFactory extension.

pull/96/head
Halil İbrahim Kalkan 9 years ago
parent
commit
dfb383fb82
  1. 2
      src/AbpDesk/AbpDesk.ConsoleDemo/AbpDesk/ConsoleDemo/Program.cs
  2. 14
      src/Volo.Abp.Autofac/Microsoft/Extensions/DependencyInjection/AbpAutofacServiceCollectionExtensions.cs
  3. 12
      src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpMethodInvocationAdapter.cs
  4. 2
      src/Volo.Abp.TestBase/AbpIntegratedTest.cs
  5. 50
      src/Volo.Abp/Microsoft/Extensions/DependencyInjection/ServiceCollectionCommonExtensions.cs
  6. 5
      test/AbpDesk/AbpDesk.Application.Tests/AbpDesk/AbpDeskApplicationTestBase.cs
  7. 12
      test/Volo.Abp.Autofac.Tests/Volo/Abp/Autofac/Interception/Autofac_Interception_Test.cs
  8. 39
      test/Volo.Abp.Tests/Volo/Abp/DynamicProxy/AbpInterceptionTestBase.cs
  9. 18
      test/Volo.Abp.Tests/Volo/Abp/DynamicProxy/CachedTestObject.cs
  10. 37
      test/Volo.Abp.Tests/Volo/Abp/DynamicProxy/SimpleResultCacheTestInterceptor.cs

2
src/AbpDesk/AbpDesk.ConsoleDemo/AbpDesk/ConsoleDemo/Program.cs

@ -31,7 +31,7 @@ namespace AbpDesk.ConsoleDemo
AddPlugIns(options);
});
using (var scope = services.BuildAutofacServiceProvider().CreateScope())
using (var scope = services.BuildServiceProviderFromFactory().CreateScope())
{
application.Initialize(scope.ServiceProvider);

14
src/Volo.Abp.Autofac/Microsoft/Extensions/DependencyInjection/AbpAutofacServiceCollectionExtensions.cs

@ -24,17 +24,7 @@ namespace Microsoft.Extensions.DependencyInjection
public static IServiceProvider BuildAutofacServiceProvider([NotNull] this IServiceCollection services, Action<ContainerBuilder> builderAction = null)
{
Check.NotNull(services, nameof(services));
var serviceProviderFactory = services.GetSingletonInstanceOrNull<IServiceProviderFactory<ContainerBuilder>>();
if (serviceProviderFactory == null)
{
throw new AbpException($"Could not find {typeof(IServiceProviderFactory<ContainerBuilder>).FullName} in {services}. Use {nameof(AbpAutofacAbpApplicationCreationOptionsExtensions.UseAutofac)} before!");
}
var builder = serviceProviderFactory.CreateBuilder(services);
builderAction?.Invoke(builder);
return serviceProviderFactory.CreateServiceProvider(builder);
return services.BuildServiceProviderFromFactory(builderAction);
}
}
}
}

12
src/Volo.Abp.Castle.Core/Volo/Abp/Castle/DynamicProxy/CastleAbpMethodInvocationAdapter.cs

@ -19,10 +19,12 @@ namespace Volo.Abp.Castle.DynamicProxy
public object ReturnValue
{
get => Invocation.ReturnValue;
get => _actualReturnValue ?? Invocation.ReturnValue;
set => Invocation.ReturnValue = value;
}
private object _actualReturnValue;
protected IInvocation Invocation { get; }
public CastleAbpMethodInvocationAdapter(IInvocation invocation)
@ -43,10 +45,10 @@ namespace Volo.Abp.Castle.DynamicProxy
public Task ProceedAsync()
{
Invocation.Proceed();
return Invocation.Method.IsAsync()
? (Task) Invocation.ReturnValue
: Task.FromResult(Invocation.ReturnValue);
_actualReturnValue = Invocation.ReturnValue;
return Invocation.Method.IsAsync()
? (Task)_actualReturnValue
: Task.FromResult(_actualReturnValue);
}
}
}

2
src/Volo.Abp.TestBase/AbpIntegratedTest.cs

@ -51,7 +51,7 @@ namespace Volo.Abp.TestBase
protected virtual IServiceProvider CreateServiceProvider(IServiceCollection services)
{
return services.BuildServiceProvider();
return services.BuildServiceProviderFromFactory();
}
public void Dispose()

50
src/Volo.Abp/Microsoft/Extensions/DependencyInjection/ServiceCollectionCommonExtensions.cs

@ -1,5 +1,9 @@
using System;
using System.Linq;
using System.Reflection;
using JetBrains.Annotations;
using Volo;
using Volo.Abp;
namespace Microsoft.Extensions.DependencyInjection
{
@ -22,5 +26,49 @@ namespace Microsoft.Extensions.DependencyInjection
return service;
}
}
public static IServiceProvider BuildServiceProviderFromFactory([NotNull] this IServiceCollection services)
{
Check.NotNull(services, nameof(services));
foreach (var service in services)
{
var factoryInterface = service.ImplementationInstance?.GetType()
.GetTypeInfo()
.GetInterfaces()
.FirstOrDefault(i => i.GetTypeInfo().IsGenericType &&
i.GetGenericTypeDefinition() == typeof(IServiceProviderFactory<>));
if (factoryInterface == null)
{
continue;
}
var containerBuilderType = factoryInterface.GenericTypeArguments[0];
return (IServiceProvider)typeof(ServiceCollectionCommonExtensions)
.GetTypeInfo()
.GetMethods()
.Single(m => m.Name == nameof(BuildServiceProviderFromFactory) && m.IsGenericMethod)
.MakeGenericMethod(containerBuilderType)
.Invoke(null, new object[] { services, null });
}
return services.BuildServiceProvider();
}
public static IServiceProvider BuildServiceProviderFromFactory<TContainerBuilder>([NotNull] this IServiceCollection services, Action<TContainerBuilder> builderAction = null)
{
Check.NotNull(services, nameof(services));
var serviceProviderFactory = services.GetSingletonInstanceOrNull<IServiceProviderFactory<TContainerBuilder>>();
if (serviceProviderFactory == null)
{
throw new AbpException($"Could not find {typeof(IServiceProviderFactory<TContainerBuilder>).FullName} in {services}.");
}
var builder = serviceProviderFactory.CreateBuilder(services);
builderAction?.Invoke(builder);
return serviceProviderFactory.CreateServiceProvider(builder);
}
}
}

5
test/AbpDesk/AbpDesk.Application.Tests/AbpDesk/AbpDeskApplicationTestBase.cs

@ -21,11 +21,6 @@ namespace AbpDesk
options.UseAutofac();
}
protected override IServiceProvider CreateServiceProvider(IServiceCollection services)
{
return services.BuildAutofacServiceProvider();
}
protected virtual void SeedTestData()
{
using (var scope = ServiceProvider.CreateScope())

12
test/Volo.Abp.Autofac.Tests/Volo/Abp/Autofac/Interception/Autofac_Interception_Test.cs

@ -1,22 +1,12 @@
using System;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Castle.DynamicProxy;
using Volo.Abp.DynamicProxy;
using Volo.Abp.DynamicProxy;
namespace Volo.Abp.Autofac.Interception
{
public class Autofac_Interception_Test : AbpInterceptionTestBase<AutofacTestModule>
{
//TODO: Sımplify using autofac in tests!
protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options)
{
options.UseAutofac();
}
protected override IServiceProvider CreateServiceProvider(IServiceCollection services)
{
return services.BuildAutofacServiceProvider();
}
}
}

39
test/Volo.Abp.Tests/Volo/Abp/DynamicProxy/AbpInterceptionTestBase.cs

@ -17,18 +17,25 @@ namespace Volo.Abp.DynamicProxy
services.AddTransient<SimpleAsyncInterceptor2>();
services.AddTransient<SimpleInterceptionTargetClass>();
services.AddTransient<SimpleResultCacheTestInterceptor>();
services.AddTransient<CachedTestObject>();
services.OnServiceRegistred(registration =>
{
//TODO: Create an attribute to add interceptors!
if (typeof(SimpleInterceptionTargetClass) == registration.ImplementationType)
{
registration.Interceptors.Add<SimpleAsyncInterceptor>();
registration.Interceptors.Add<SimpleSyncInterceptor>();
registration.Interceptors.Add<SimpleAsyncInterceptor2>();
}
if (typeof(CachedTestObject) == registration.ImplementationType)
{
registration.Interceptors.Add<SimpleResultCacheTestInterceptor>();
}
});
}
[Fact]
public async Task Should_Intercept_Async_Method_Without_Return_Value()
{
@ -125,5 +132,33 @@ namespace Volo.Abp.DynamicProxy
target.Logs[5].ShouldBe("SimpleSyncInterceptor_Intercept_AfterInvocation");
target.Logs[6].ShouldBe("SimpleAsyncInterceptor_Intercept_AfterInvocation");
}
[Fact]
public void Should_Cache_Results()
{
//Arrange
var target = ServiceProvider.GetService<CachedTestObject>();
//Act & Assert
target.GetValue(42).ShouldBe(42); //First run, not cached yet
target.GetValue(43).ShouldBe(42); //First run, cached previous value
target.GetValue(44).ShouldBe(42); //First run, cached previous value
}
[Fact]
public async Task Should_Cache_Results_Async()
{
//Arrange
var target = ServiceProvider.GetService<CachedTestObject>();
//Act & Assert
(await target.GetValueAsync(42)).ShouldBe(42); //First run, not cached yet
(await target.GetValueAsync(43)).ShouldBe(42); //First run, cached previous value
(await target.GetValueAsync(44)).ShouldBe(42); //First run, cached previous value
}
}
}

18
test/Volo.Abp.Tests/Volo/Abp/DynamicProxy/CachedTestObject.cs

@ -0,0 +1,18 @@
using System.Threading.Tasks;
namespace Volo.Abp.DynamicProxy
{
public class CachedTestObject
{
public virtual int GetValue(int v)
{
return v;
}
public virtual async Task<int> GetValueAsync(int v)
{
await Task.Delay(5);
return v;
}
}
}

37
test/Volo.Abp.Tests/Volo/Abp/DynamicProxy/SimpleResultCacheTestInterceptor.cs

@ -0,0 +1,37 @@
using System.Collections.Concurrent;
using System.Reflection;
using System.Threading.Tasks;
namespace Volo.Abp.DynamicProxy
{
public class SimpleResultCacheTestInterceptor : AbpInterceptor
{
private readonly ConcurrentDictionary<MethodInfo, object> _cache;
public SimpleResultCacheTestInterceptor()
{
_cache = new ConcurrentDictionary<MethodInfo, object>();
}
public override void Intercept(IAbpMethodInvocation invocation)
{
invocation.ReturnValue = _cache.GetOrAdd(invocation.Method, m =>
{
invocation.Proceed();
return invocation.ReturnValue;
});
}
public override async Task InterceptAsync(IAbpMethodInvocation invocation)
{
if (_cache.ContainsKey(invocation.Method))
{
invocation.ReturnValue = _cache[invocation.Method];
return;
}
await invocation.ProceedAsync();
_cache[invocation.Method] = invocation.ReturnValue;
}
}
}
Loading…
Cancel
Save