using System; using System.Collections.Generic; using System.IO; using System.Reflection; using System.Text.RegularExpressions; using System.Threading.Tasks; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using Props.Models.Search; using Props.Options; using Props.Shop.Framework; namespace Props.Services.Modules { public class LocalShopManager : IShopManager { private ILogger logger; private Dictionary shops; private ModulesOptions options; private IConfiguration configuration; public LocalShopManager(IConfiguration configuration, ILogger logger) { this.configuration = configuration; this.logger = logger; options = configuration.GetSection(ModulesOptions.Modules).Get(); shops = new Dictionary(); foreach (IShop shop in LoadShops(options.ShopsDir, options.ShopRegex, options.RecursiveLoad)) { if (!shops.TryAdd(shop.ShopName, shop)) { logger.LogWarning("Duplicate shop {0} detected. Ignoring the latter.", shop.ShopName); } } } public IEnumerable AvailableShops() { return shops.Keys; } public async Task> Search(string query, SearchOutline searchOutline) { List results = new List(); foreach (string shopName in shops.Keys) { if (!searchOutline.Disabled[shopName]) { int amount = 0; await foreach (ProductListing product in shops[shopName].Search(query, searchOutline.Filters)) { if (searchOutline.Filters.Validate(product)) { amount += 1; results.Add(product); } if (amount >= options.MaxResults) break; } } } return results; } private IEnumerable LoadShops(string shopsDir, string shopRegex, bool recursiveLoad) { Stack directories = new Stack(); directories.Push(shopsDir); string currentDirectory = null; while (directories.TryPop(out currentDirectory)) { if (recursiveLoad) { foreach (string dir in Directory.EnumerateDirectories(currentDirectory)) { directories.Push(dir); } } foreach (string file in Directory.EnumerateFiles(currentDirectory)) { if (Path.GetExtension(file).Equals(".dll") && Regex.IsMatch(file, shopRegex)) { ShopAssemblyLoadContext context = new ShopAssemblyLoadContext(file); Assembly assembly = context.LoadFromAssemblyName(new AssemblyName(Path.GetFileNameWithoutExtension(file))); int success = 0; foreach (Type type in assembly.GetTypes()) { if (typeof(IShop).IsAssignableFrom(type)) { IShop shop = Activator.CreateInstance(type) as IShop; if (shop != null) { success += 1; yield return shop; } } } if (success == 0) { logger.LogWarning("There were no shops found within the assembly at path \"{0}\".", file); } } } } } } }