internal static Task <IList <T> > Init <T>(string workingDir, ILogger logger, ILocalizationProvider localizationProvider) { IList <T> retT = new List <T>(); foreach (var file in Directory.GetFiles(workingDir, "*Factory*.dll")) { var loader = new AssemblyLoader(workingDir, workingDir); Assembly AssemblyLoader(AssemblyLoadContext context, AssemblyName name) { logger.LogInformation($"Try to load assembly {name} for {file}"); // avoid loading *.resources dlls, because of: https://github.com/dotnet/coreclr/issues/8416 if (name.Name.EndsWith("resources")) { return(null); } logger.LogInformation($"try to load assembly from {workingDir}"); var foundDlls = Directory.GetFileSystemEntries(workingDir, name.Name + ".dll", SearchOption.AllDirectories); if (foundDlls.Any()) { return(context.LoadFromAssemblyPath(foundDlls[0])); } var secondPath = new FileInfo(Assembly.GetExecutingAssembly().Location).DirectoryName; logger.LogDebug($"try to load assembly from second path: {secondPath}"); foundDlls = Directory.GetFileSystemEntries(secondPath, name.Name + ".dll", SearchOption.AllDirectories); if (foundDlls.Any()) { return(context.LoadFromAssemblyPath(foundDlls[0])); } return(context.LoadFromAssemblyName(name)); } Assembly assembly; try { AssemblyLoadContext.Default.Resolving += AssemblyLoader; logger.LogInformation($"Loading file {file}"); assembly = loader.LoadFromAssemblyPath(file); } catch (Exception e) { logger.LogError(e, $"Could not load assembly {file}"); continue; } finally { AssemblyLoadContext.Default.Resolving -= AssemblyLoader; } var resources = assembly.GetManifestResourceNames().SingleOrDefault(a => a.EndsWith("automatica-manifest.json")); if (resources == null) { continue; } var manifest = Common.Update.Plugin.GetEmbeddedPluginManifest(logger, assembly); if (manifest.Automatica.Type == "driver") { var drivers = assembly.GetExportedTypes().Where(a => a.IsSubclassOf(typeof(T))); foreach (var driver in drivers) { if (assembly.CreateInstance(driver.FullName) is T factory) { retT.Add(factory); } } } localizationProvider.LoadFromAssembly(assembly); } return(Task.FromResult(retT)); }
public Task Load(IDriverFactory factory, IBoardType boardType) { try { var manifest = Common.Update.Plugin.GetEmbeddedPluginManifest(_logger, factory.GetType().Assembly); if (manifest == null) { throw new NoManifestFoundException(); } _store.Add(manifest.Automatica.PluginGuid, manifest); _driverFactoryStore.Add(factory.DriverGuid, factory); _logger.LogDebug($"Init driver {factory.DriverName} {factory.DriverVersion}..."); var driverDbVersion = _dbContext.VersionInformations.SingleOrDefault(a => a.DriverGuid == factory.DriverGuid); var initNodeTemplates = false; if (driverDbVersion == null) { driverDbVersion = new VersionInformation { Name = factory.DriverName, Version = factory.DriverVersion.ToString(), DriverGuid = factory.DriverGuid }; initNodeTemplates = true; _dbContext.VersionInformations.Add(driverDbVersion); } else if (factory.DriverVersion > driverDbVersion.VersionData) { initNodeTemplates = true; driverDbVersion.Name = factory.DriverName; driverDbVersion.Version = factory.DriverVersion.ToString(); } if (!UsesInterface(boardType, factory)) { _logger.LogInformation( $"Ignore {factory.DriverName} because we do not support any of the given interfaces"); return(Task.CompletedTask); } _localizationProvider.LoadFromAssembly(factory.GetType().Assembly); if (initNodeTemplates || factory.InDevelopmentMode) { _logger.LogDebug($"InitNodeTemplates for {factory.DriverName}..."); using (var db = new AutomaticaContext(_config)) { factory.InitNodeTemplates(new NodeTemplateFactory(db, _config)); db.SaveChanges(); } _logger.LogDebug($"InitNodeTemplates for {factory.DriverName}...done"); } else { factory.InitNodeTemplates(new DoNothingNodeTemplateFactory()); } _logger.LogDebug($"Init driver {factory.DriverName} {factory.DriverVersion}...done"); _dbContext.SaveChanges(); } catch (NoManifestFoundException) { // ignore } catch (Exception e) { _logger.LogError($"Could not load driver {factory.DriverName} {e}", e); } return(Task.CompletedTask); }