Created BuildServiceProviderFromFactory extension.

pull/96/head
Halil İbrahim Kalkan 9 years ago
parent 98baf4c5d6
commit dfb383fb82

@ -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);

@ -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);
}
}
}
}

@ -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);
}
}
}

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

@ -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);
}
}
}

@ -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())

@ -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();
}
}
}

@ -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
}
}
}

@ -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;
}
}
}

@ -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