diff --git a/Source/Platibus/Config/ReflectionService.cs b/Source/Platibus/Config/ReflectionService.cs index 6d0e1b0f..6e6f040c 100644 --- a/Source/Platibus/Config/ReflectionService.cs +++ b/Source/Platibus/Config/ReflectionService.cs @@ -20,12 +20,13 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +using Microsoft.Extensions.DependencyModel; +using Platibus.Diagnostics; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; -using Platibus.Diagnostics; namespace Platibus.Config { @@ -44,6 +45,48 @@ public ReflectionService(IDiagnosticService diagnosticService) } public IEnumerable FindConcreteSubtypes() + { + var appDomain = AppDomain.CurrentDomain; + var assemblyNames = GetAssemblyNames(appDomain); + var subtypes = new List(); + foreach (var assemblyName in assemblyNames) + { + try + { + var assembly = appDomain.GetAssemblies() + .FirstOrDefault(a => a.GetName() == assemblyName) + ?? appDomain.Load(assemblyName); + + subtypes.AddRange(assembly.GetTypes() + .Where(typeof(TBase).IsAssignableFrom) + .Where(t => !t.IsInterface && !t.IsAbstract)); + } + catch (Exception ex) + { + _diagnosticService.Emit(new DiagnosticEventBuilder(this, DiagnosticEventType.TypeLoadFailed) + { + Detail = $"Error loading assembly {assemblyName}", + Exception = ex + }.Build()); + } + } + return subtypes; + } + + public IEnumerable GetAssemblyNames(AppDomain appDomain) + { + return GetDefaultAssemblyNames() + .Union(GetAppDomainBaseDirectoryAssemblyNames(appDomain)) + .Distinct(new AssemblyNameEqualityComparer()); + } + + public IEnumerable GetDefaultAssemblyNames() + { + var dependencyContext = DependencyContext.Default; + return dependencyContext?.GetDefaultAssemblyNames() ?? Enumerable.Empty(); + } + + public IEnumerable GetAppDomainBaseDirectoryAssemblyNames(AppDomain appDomain) { var appDomainBaseDirectory = AppDomain.CurrentDomain.BaseDirectory; var directories = new[] @@ -62,20 +105,13 @@ public IEnumerable FindConcreteSubtypes() .Where(dir => dir.Directory.Exists) .SelectMany(x => x.Directory.GetFiles(x.FilenamePattern, SearchOption.TopDirectoryOnly)); - var subtypes = new List(); + var assemblyNames = new List(); foreach (var assemblyFile in assemblyFiles) { try { var assemblyName = AssemblyName.GetAssemblyName(assemblyFile.FullName); - var appDomain = AppDomain.CurrentDomain; - var assembly = appDomain.GetAssemblies() - .FirstOrDefault(a => a.GetName() == assemblyName) - ?? appDomain.Load(assemblyName); - - subtypes.AddRange(assembly.GetTypes() - .Where(typeof(TBase).IsAssignableFrom) - .Where(t => !t.IsInterface && !t.IsAbstract)); + assemblyNames.Add(assemblyName); } catch (Exception ex) { @@ -84,9 +120,23 @@ public IEnumerable FindConcreteSubtypes() Detail = $"Error loading assembly file {assemblyFile.FullName}", Exception = ex }.Build()); - } + } + } + + return assemblyNames; + } + + private class AssemblyNameEqualityComparer : IEqualityComparer + { + public bool Equals(AssemblyName x, AssemblyName y) + { + return Equals(x.Name, y.Name); + } + + public int GetHashCode(AssemblyName obj) + { + return obj?.Name.GetHashCode() ?? 0; } - return subtypes; } } } \ No newline at end of file diff --git a/Source/Platibus/Platibus.csproj b/Source/Platibus/Platibus.csproj index 1a9624bf..9998ccf3 100644 --- a/Source/Platibus/Platibus.csproj +++ b/Source/Platibus/Platibus.csproj @@ -16,6 +16,7 @@ +