mirror of https://github.com/abpframework/abp.git
17 changed files with 270 additions and 45 deletions
@ -0,0 +1,16 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace Volo.Abp.Modularity |
|||
{ |
|||
public interface IAbpModuleDescriptor |
|||
{ |
|||
Type Type { get; } |
|||
|
|||
IAbpModule Instance { get; } |
|||
|
|||
bool IsLoadedAsPlugIn { get; } |
|||
|
|||
IReadOnlyList<IAbpModuleDescriptor> Dependencies { get; } |
|||
} |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
using System.Collections.Generic; |
|||
using JetBrains.Annotations; |
|||
|
|||
namespace Volo.Abp.Modularity |
|||
{ |
|||
public interface IModuleContainer |
|||
{ |
|||
[NotNull] |
|||
IReadOnlyList<IAbpModuleDescriptor> Modules { get; } |
|||
} |
|||
} |
|||
@ -0,0 +1,38 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Collections.Immutable; |
|||
using System.Linq; |
|||
using System.Reflection; |
|||
using System.Threading; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace Volo.Abp.Reflection |
|||
{ |
|||
public class AssemblyFinder : IAssemblyFinder |
|||
{ |
|||
private readonly IModuleContainer _moduleContainer; |
|||
|
|||
private readonly Lazy<IReadOnlyList<Assembly>> _assemblies; |
|||
|
|||
public AssemblyFinder(IModuleContainer moduleContainer) |
|||
{ |
|||
_moduleContainer = moduleContainer; |
|||
|
|||
_assemblies = new Lazy<IReadOnlyList<Assembly>>(FindAll, LazyThreadSafetyMode.ExecutionAndPublication); |
|||
} |
|||
|
|||
public IReadOnlyList<Assembly> Assemblies => _assemblies.Value; |
|||
|
|||
public IReadOnlyList<Assembly> FindAll() |
|||
{ |
|||
var assemblies = new List<Assembly>(); |
|||
|
|||
foreach (var module in _moduleContainer.Modules) |
|||
{ |
|||
assemblies.Add(module.Type.GetAssembly()); |
|||
} |
|||
|
|||
return assemblies.Distinct().ToImmutableList(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,14 @@ |
|||
using System.Collections.Generic; |
|||
using System.Reflection; |
|||
|
|||
namespace Volo.Abp.Reflection |
|||
{ |
|||
/// <summary>
|
|||
/// Used to get assemblies in the application.
|
|||
/// It may not return all assemblies, but those are related with modules.
|
|||
/// </summary>
|
|||
public interface IAssemblyFinder |
|||
{ |
|||
IReadOnlyList<Assembly> Assemblies { get; } |
|||
} |
|||
} |
|||
@ -0,0 +1,14 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace Volo.Abp.Reflection |
|||
{ |
|||
/// <summary>
|
|||
/// Used to get types in the application.
|
|||
/// It may not return all types, but those are related with modules.
|
|||
/// </summary>
|
|||
public interface ITypeFinder |
|||
{ |
|||
IReadOnlyList<Type> Types { get; } |
|||
} |
|||
} |
|||
@ -0,0 +1,65 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Reflection; |
|||
using System.Threading; |
|||
using Microsoft.Extensions.Logging; |
|||
using Volo.ExtensionMethods.Collections.Generic; |
|||
|
|||
namespace Volo.Abp.Reflection |
|||
{ |
|||
//TODO: Write unit tests!
|
|||
|
|||
public class TypeFinder : ITypeFinder |
|||
{ |
|||
private readonly IAssemblyFinder _assemblyFinder; |
|||
private readonly ILogger<TypeFinder> _logger; |
|||
|
|||
private readonly Lazy<IReadOnlyList<Type>> _types; |
|||
|
|||
public TypeFinder(IAssemblyFinder assemblyFinder, ILogger<TypeFinder> logger) |
|||
{ |
|||
_assemblyFinder = assemblyFinder; |
|||
_logger = logger; |
|||
|
|||
_types = new Lazy<IReadOnlyList<Type>>(FindAll, LazyThreadSafetyMode.ExecutionAndPublication); |
|||
} |
|||
|
|||
public IReadOnlyList<Type> Types => _types.Value; |
|||
|
|||
private IReadOnlyList<Type> FindAll() |
|||
{ |
|||
var allTypes = new List<Type>(); |
|||
|
|||
foreach (var assembly in _assemblyFinder.Assemblies) |
|||
{ |
|||
try |
|||
{ |
|||
Type[] typesInThisAssembly; |
|||
|
|||
try |
|||
{ |
|||
typesInThisAssembly = assembly.GetTypes(); |
|||
} |
|||
catch (ReflectionTypeLoadException ex) |
|||
{ |
|||
typesInThisAssembly = ex.Types; |
|||
} |
|||
|
|||
if (typesInThisAssembly.IsNullOrEmpty()) |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
allTypes.AddRange(typesInThisAssembly.Where(type => type != null)); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
_logger.LogWarning(ex.ToString()); |
|||
} |
|||
} |
|||
|
|||
return allTypes; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,57 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using NSubstitute; |
|||
using Shouldly; |
|||
using Volo.Abp.Modularity; |
|||
using Xunit; |
|||
|
|||
namespace Volo.Abp.Reflection |
|||
{ |
|||
public class AssemblyFinder_Tests |
|||
{ |
|||
[Theory] |
|||
[InlineData(new object[] { new Type[] { } })] |
|||
[InlineData(new object[] { new[] { typeof(IndependentEmptyModule) } })] |
|||
[InlineData(new object[] { new[] { typeof(AbpKernelModule), typeof(IndependentEmptyModule) } })] |
|||
public void Should_Get_Assemblies_Of_All_Modules(Type[] moduleTypes) |
|||
{ |
|||
//Arrange
|
|||
|
|||
var fakeModuleContainer = CreateFakeModuleContainer(moduleTypes); |
|||
|
|||
//Act
|
|||
|
|||
var assemblyFinder = new AssemblyFinder(fakeModuleContainer); |
|||
|
|||
//Assert
|
|||
|
|||
assemblyFinder.Assemblies.Count.ShouldBe(moduleTypes.Length); |
|||
|
|||
foreach (var moduleType in moduleTypes) |
|||
{ |
|||
assemblyFinder.Assemblies.ShouldContain(moduleType.GetAssembly()); |
|||
} |
|||
} |
|||
|
|||
private static IModuleContainer CreateFakeModuleContainer(IEnumerable<Type> moduleTypes) |
|||
{ |
|||
var moduleDescriptors = moduleTypes.Select(CreateModuleDescriptor).ToList(); |
|||
return CreateFakeModuleContainer(moduleDescriptors); |
|||
} |
|||
|
|||
private static IModuleContainer CreateFakeModuleContainer(List<IAbpModuleDescriptor> moduleDescriptors) |
|||
{ |
|||
var fakeModuleContainer = Substitute.For<IModuleContainer>(); |
|||
fakeModuleContainer.Modules.Returns(moduleDescriptors); |
|||
return fakeModuleContainer; |
|||
} |
|||
|
|||
private static IAbpModuleDescriptor CreateModuleDescriptor(Type moduleType) |
|||
{ |
|||
var moduleDescriptor = Substitute.For<IAbpModuleDescriptor>(); |
|||
moduleDescriptor.Type.Returns(moduleType); |
|||
return moduleDescriptor; |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue