// /* ============================================================================ // Copyright 2014 Hewlett Packard // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ============================================================================ */ namespace Openstack.Common.ServiceLocation { using System; using System.Collections.Generic; using System.Linq; using System.Reflection; /// internal class ServiceLocationAssemblyScanner : IServiceLocationAssemblyScanner { private IServiceLocationRegistrarFactory ServiceRegistrarFactory { get; set; } private readonly List _registrars = new List(); private readonly List _assemblies = new List(); /// /// Gets and sets a list of assemblies that have been scanned. /// internal Func> GetAllAssemblies { get; set; } /// /// Creates a new instance of the ServiceLocationAssemblyScanner class. /// public ServiceLocationAssemblyScanner() { this.GetAllAssemblies = this.InternalGetAllAssemblies; this.ServiceRegistrarFactory = new ServiceLocationRegistrarFactory(); } /// /// Gets a list of all assemblies in the current application domain. /// /// A list of assembly objects. internal IEnumerable InternalGetAllAssemblies() { return AppDomain.CurrentDomain.GetAssemblies(); } /// public bool HasNewAssemblies() { var assemblies = this.GetAllAssemblies().ToList(); this._assemblies.All(assemblies.Remove); this._assemblies.AddRange(assemblies); return assemblies.Any(); } /// public IEnumerable GetRegistrars() { var newRegistrars = new List(); if (this.HasNewAssemblies()) { newRegistrars = this.GetRegistrarTypes().ToList(); } this._registrars.All(newRegistrars.Remove); this._registrars.AddRange(newRegistrars); var objects = (from t in this._registrars select ServiceRegistrarFactory.Create(t)).ToList(); return objects; } /// /// Gets a list of types for any services registrars in the current application domain. /// /// A list of types. internal IEnumerable GetRegistrarTypes() { var comparer = new AssemblyNameEqualityComparer(); var rawTypes = new List(); var scansedAssemblies = this.GetAllAssemblies(); var workingAssemblies = (from s in scansedAssemblies where s.GetReferencedAssemblies().Contains(typeof(IServiceLocationRegistrar).Assembly.GetName(), comparer) select s).ToList(); workingAssemblies.Add(this.GetType().Assembly); foreach (var assembly in workingAssemblies) { try { rawTypes.AddRange(assembly.GetTypes()); } catch (ReflectionTypeLoadException loadEx) { var foundTypes = (from t in loadEx.Types where t != null select t).ToList(); rawTypes.AddRange(foundTypes); } } var unorderedTypes = new Queue(); foreach (var type in rawTypes) { if (type.IsInterface) { continue; } if (typeof(IServiceLocationRegistrar).IsAssignableFrom(type) && !ReferenceEquals(type.GetConstructor(new Type[0]), null)) { unorderedTypes.Enqueue(type); } } var registrarTypes = new List(); while (unorderedTypes.Count > 0) { var type = unorderedTypes.Dequeue(); var addToTypesList = true; foreach (var stackType in unorderedTypes) { if (!type.Assembly.GetReferencedAssemblies().Contains(stackType.Assembly.GetName(), comparer)) { continue; } addToTypesList = false; unorderedTypes.Enqueue(type); break; } if (addToTypesList) { registrarTypes.Add(type); } } return registrarTypes; } } }