Browse Source

Refactored ServiceCollectionRegistrationExtensions, added TryAdd methods.

pull/81/head
Halil İbrahim Kalkan 10 years ago
parent
commit
8545c361f7
  1. 2
      src/Volo.Abp/Volo/Abp/Uow/UnitOfWorkManager.cs
  2. 121
      src/Volo.DependencyInjection/Microsoft/Extensions/DependencyInjection/ServiceCollectionRegistrationExtensions.cs
  3. 52
      src/Volo.DependencyInjection/Volo/DependencyInjection/AutoRegistrationHelper.cs
  4. 55
      test/Volo.DependencyInjection.Tests/Volo/DependencyInjection/AutoRegistrationHelper_Tests.cs

2
src/Volo.Abp/Volo/Abp/Uow/UnitOfWorkManager.cs

@ -36,7 +36,7 @@ namespace Volo.Abp.Uow
scope
);
}
catch
catch(Exception ex)
{
scope.Dispose();
throw;

121
src/Volo.DependencyInjection/Microsoft/Extensions/DependencyInjection/ServiceCollectionRegistrationExtensions.cs

@ -1,9 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Volo.DependencyInjection;
using Volo.ExtensionMethods;
using Volo.Internal;
namespace Microsoft.Extensions.DependencyInjection
@ -12,83 +12,122 @@ namespace Microsoft.Extensions.DependencyInjection
{
//TODO: Check if assembly/type is added before or add TryAdd versions of them?
//TODO: When to use Add, when to use TryAdd? We may think to add conventional interfaces to indicate and attributes to override them.
//TODO: Make this code extensible, so we can add other conventions!
public static IServiceCollection AddAssemblyOf<T>(this IServiceCollection services)
{
return services.AddAssembly(typeof(T).GetTypeInfo().Assembly);
return services.AddAssemblyOf<T>(false);
}
public static IServiceCollection TryAddAssemblyOf<T>(this IServiceCollection services)
{
return services.AddAssemblyOf<T>(true);
}
public static IServiceCollection AddAssembly(this IServiceCollection services, Assembly assembly)
{
var types = AssemblyHelper.GetAllTypes(assembly).Where(t =>
{
var typeInfo = t.GetTypeInfo();
return typeInfo.IsClass && !typeInfo.IsAbstract && !typeInfo.IsGenericType && !typeInfo.IsDefined(typeof(SkipAutoRegistrationAttribute));
});
return services.AddAssembly(assembly, false);
}
return services.AddTypes(types.ToArray());
public static IServiceCollection TryAddAssembly(this IServiceCollection services, Assembly assembly)
{
return services.AddAssembly(assembly, true);
}
public static IServiceCollection AddTypes(this IServiceCollection services, params Type[] types)
{
return services.AddTypes(false, types);
}
public static IServiceCollection TryAddTypes(this IServiceCollection services, params Type[] types)
{
return services.AddTypes(true, types);
}
public static IServiceCollection AddType(this IServiceCollection services, Type type)
{
return services.AddType(type, false);
}
public static IServiceCollection TryAddType(this IServiceCollection services, Type type)
{
return services.AddType(type, true);
}
internal static IServiceCollection AddAssemblyOf<T>(this IServiceCollection services, bool tryAdd)
{
return services.AddAssembly(typeof(T).GetTypeInfo().Assembly, tryAdd);
}
internal static IServiceCollection AddAssembly(this IServiceCollection services, Assembly assembly, bool tryAdd)
{
var types = AssemblyHelper
.GetAllTypes(assembly)
.Where(t =>
{
var typeInfo = t.GetTypeInfo();
return typeInfo.IsClass &&
!typeInfo.IsAbstract &&
!typeInfo.IsGenericType &&
!typeInfo.IsDefined(typeof(SkipAutoRegistrationAttribute));
});
return services.AddTypes(tryAdd, types.ToArray());
}
internal static IServiceCollection AddTypes(this IServiceCollection services, bool tryAdd, params Type[] types)
{
foreach (var type in types)
{
services.AddType(type);
services.AddType(type, tryAdd);
}
return services;
}
public static IServiceCollection AddType(this IServiceCollection services, Type type)
internal static IServiceCollection AddType(this IServiceCollection services, Type type, bool tryAdd)
{
//TODO: Make this code extensible, so we can add other conventions!
foreach (var serviceType in FindServiceTypes(type))
var lifeTime = GetServiceLifeTime(type);
if (lifeTime == null)
{
if (typeof(ITransientDependency).GetTypeInfo().IsAssignableFrom(type))
{
services.AddTransient(serviceType, type);
}
if (typeof(ISingletonDependency).GetTypeInfo().IsAssignableFrom(type))
return services;
}
foreach (var serviceType in AutoRegistrationHelper.GetExposedServices(type))
{
var serviceDescriptor = ServiceDescriptor.Describe(serviceType, type, lifeTime.Value);
if (tryAdd)
{
services.AddSingleton(serviceType, type);
services.Add(serviceDescriptor);
}
if (typeof(IScopedDependency).GetTypeInfo().IsAssignableFrom(type))
else
{
services.AddScoped(serviceType, type);
services.TryAdd(serviceDescriptor);
}
}
return services;
}
private static IEnumerable<Type> FindServiceTypes(Type type)
[CanBeNull]
internal static ServiceLifetime? GetServiceLifeTime(Type type)
{
var customExposedServices = type.GetTypeInfo().GetCustomAttributes().OfType<IExposedServiceTypesProvider>().SelectMany(p => p.GetExposedServiceTypes()).ToList();
if (customExposedServices.Any())
if (typeof(ITransientDependency).GetTypeInfo().IsAssignableFrom(type))
{
return customExposedServices;
return ServiceLifetime.Transient;
}
var serviceTypes = new List<Type> { type };
foreach (var interfaceType in type.GetTypeInfo().GetInterfaces())
if (typeof(ISingletonDependency).GetTypeInfo().IsAssignableFrom(type))
{
var interfaceName = interfaceType.Name;
if (interfaceName.StartsWith("I"))
{
interfaceName = interfaceName.Right(interfaceName.Length - 1);
}
return ServiceLifetime.Singleton;
}
if (type.Name.EndsWith(interfaceName))
{
serviceTypes.Add(interfaceType);
}
if (typeof(IScopedDependency).GetTypeInfo().IsAssignableFrom(type))
{
return ServiceLifetime.Scoped;
}
return serviceTypes;
return null;
}
}
}

52
src/Volo.DependencyInjection/Volo/DependencyInjection/AutoRegistrationHelper.cs

@ -0,0 +1,52 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Volo.ExtensionMethods;
namespace Volo.DependencyInjection
{
public static class AutoRegistrationHelper
{
public static IEnumerable<Type> GetExposedServices(Type type)
{
var typeInfo = type.GetTypeInfo();
var customExposedServices = typeInfo
.GetCustomAttributes()
.OfType<IExposedServiceTypesProvider>()
.SelectMany(p => p.GetExposedServiceTypes())
.ToList();
if (customExposedServices.Any())
{
return customExposedServices;
}
return GetDefaultExposedServices(type);
}
private static IEnumerable<Type> GetDefaultExposedServices(Type type)
{
var typeInfo = type.GetTypeInfo();
var serviceTypes = new List<Type> { type };
foreach (var interfaceType in typeInfo.GetInterfaces())
{
var interfaceName = interfaceType.Name;
if (interfaceName.StartsWith("I"))
{
interfaceName = interfaceName.Right(interfaceName.Length - 1);
}
if (type.Name.EndsWith(interfaceName))
{
serviceTypes.Add(interfaceType);
}
}
return serviceTypes;
}
}
}

55
test/Volo.DependencyInjection.Tests/Volo/DependencyInjection/AutoRegistrationHelper_Tests.cs

@ -0,0 +1,55 @@
using System.Linq;
using Shouldly;
using Xunit;
namespace Volo.DependencyInjection
{
public class AutoRegistrationHelper_Tests
{
[Fact]
public void Should_Get_Conventional_Exposed_Types_By_Default()
{
//Act
var exposedServices = AutoRegistrationHelper.GetExposedServices(typeof(DefaultDerivedService)).ToList();
//Assert
exposedServices.Count.ShouldBe(3);
exposedServices.ShouldContain(typeof(DefaultDerivedService));
exposedServices.ShouldContain(typeof(IService));
exposedServices.ShouldContain(typeof(IDerivedService));
}
[Fact]
public void Should_Get_Custom_Exposed_Types_If_Available()
{
//Act
var exposedServices = AutoRegistrationHelper.GetExposedServices(typeof(ExplicitDerivedService)).ToList();
//Assert
exposedServices.Count.ShouldBe(1);
exposedServices.ShouldContain(typeof(IDerivedService));
}
public class DefaultDerivedService : IDerivedService
{
}
public interface IService
{
}
public interface IDerivedService : IService
{
}
[ExposeServices(typeof(IDerivedService))]
public class ExplicitDerivedService : IDerivedService
{
}
}
}
Loading…
Cancel
Save