using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using CTA.FeatureDetection.Common; using CTA.FeatureDetection.Common.Exceptions; using CTA.FeatureDetection.Common.Models.Configuration; using CTA.FeatureDetection.Common.Models.Enums; using CTA.FeatureDetection.Common.Models.Features.Base; using CTA.FeatureDetection.Load.Factories; using Microsoft.Extensions.Logging; namespace CTA.FeatureDetection.Load.Loaders { /// /// Loads features into memory from features metadata objects /// public class FeatureLoader { private static ILogger Logger => Log.Logger; /// /// Loads compiled features from an assembly specified in a metadata collection /// /// The scope in which to look for the features /// Collection of feature assembly metadata /// Collection of compiled feature instances public static HashSet LoadCompiledFeaturesFromAssemblies( FeatureScope featureScope, CompiledFeatureAssembly[] compiledFeatureAssemblies) { var loadedFeatures = new HashSet(); foreach (var compiledFeatureAssembly in compiledFeatureAssemblies) { try { var compiledFeatures = LoadCompiledFeaturesFromAssembly(featureScope, compiledFeatureAssembly); loadedFeatures.UnionWith(compiledFeatures); } catch (FileNotFoundException ex) { Logger.LogError(ex, $"Could not find assembly {compiledFeatureAssembly.AssemblyPath}"); } } return loadedFeatures; } /// /// Loads configured features using metadata /// /// The scope in which to look for the features /// Collection of configured feature metadata /// Collection of configured feature instances public static HashSet LoadConfiguredFeatures(FeatureScope featureScope, ConfiguredFeatureMetadata[] configuredFeatures) { var loadedConfiguredFeatures = new HashSet(); foreach (var configuredFeature in configuredFeatures) { try { if (configuredFeature.ConditionGroups != null && configuredFeature.ConditionGroups.Any()) { var loadedFeature = ConfiguredFeatureFactory.GetInstance(featureScope, configuredFeature.Name, configuredFeature.ConditionGroups); loadedConfiguredFeatures.Add(loadedFeature); } else if (configuredFeature.ConditionGroup != null) { var loadedFeature = ConfiguredFeatureFactory.GetInstance(featureScope, configuredFeature.Name, configuredFeature.ConditionGroup); loadedConfiguredFeatures.Add(loadedFeature); } else if (configuredFeature.Condition != null) { var loadedFeature = ConfiguredFeatureFactory.GetInstance(featureScope, configuredFeature.Name, configuredFeature.Condition); loadedConfiguredFeatures.Add(loadedFeature); } } catch (Exception ex) { Log.Logger.LogError(ex, $"Error encountered when trying to load ConfiguredFeature {configuredFeature.Name}."); Console.WriteLine(ex); } } return loadedConfiguredFeatures; } /// /// Dynamically instantiates all features in a given namespaceSuffix /// /// Assembly containing the feature types /// Namespace containing the feature types /// Instances of all features in the namespace with the given suffix public static IEnumerable LoadFeaturesFromNamespace(Assembly assembly, string namespaceSuffix) { var loadedFeatures = new List(); if (assembly == null || string.IsNullOrEmpty(namespaceSuffix)) { return loadedFeatures; } var featureScope = FeatureScope.Undefined; var featureTypes = assembly.GetTypes().Where(t => t.Namespace != null && t.Namespace.EndsWith(namespaceSuffix)); foreach (var featureType in featureTypes) { var featureMetadata = new CompiledFeatureMetadata { Name = featureType.Name, ClassName = featureType.Name }; try { var loadedFeature = CompiledFeatureFactory.GetInstance(featureScope, assembly, featureType.Namespace, featureMetadata); loadedFeatures.Add(loadedFeature); } catch (Exception ex) { Logger.LogError(ex, ex.Message); } } return loadedFeatures; } /// /// Dynamically instantiates all features in a given collection of CompiledFeature types /// /// CompiledFeature types to instantiate /// CompiledFeature instances public static IEnumerable LoadFeaturesByTypes(IEnumerable types) { var loadedFeatures = new List(); foreach (var type in types) { try { var loadedFeature = LoadFeaturesByType(type); loadedFeatures.Add(loadedFeature); } catch (Exception ex) { Logger.LogError(ex, ex.Message); } } return loadedFeatures; } /// /// Dynamically instantiates a CompiledFeature by its type /// /// CompiledFeature type to instantiate /// CompiledFeature instance public static CompiledFeature LoadFeaturesByType(Type type) { return CompiledFeatureFactory.GetInstance(type); } private static HashSet LoadCompiledFeaturesFromAssembly(FeatureScope featureScope, CompiledFeatureAssembly compiledFeatureAssembly) { var loadedFeatures = new HashSet(); var loadedAssembly = Assembly.LoadFile(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), compiledFeatureAssembly.AssemblyPath)); foreach (var featureNamespace in compiledFeatureAssembly.CompiledFeatureNamespaces) { var compiledFeatures = LoadCompiledFeaturesByNamespace(featureScope, loadedAssembly, featureNamespace); loadedFeatures.UnionWith(compiledFeatures); } return loadedFeatures; } private static HashSet LoadCompiledFeaturesByNamespace( FeatureScope featureScope, Assembly assembly, CompiledFeatureNamespace featureNamespace) { var loadedFeatures = new HashSet(); foreach (var featureMetadata in featureNamespace.CompiledFeatureMetadata) { try { var compiledFeature = CompiledFeatureFactory.GetInstance(featureScope, assembly, featureNamespace.Namespace, featureMetadata); loadedFeatures.Add(compiledFeature); } catch (ClassNotFoundException e) { Logger.LogError(e, e.Message); } catch (InvalidFeatureException e) { Logger.LogError(e, e.Message); } } return loadedFeatures; } } }