2021-07-22 21:12:27 +00:00
|
|
|
using System;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.IO;
|
2021-08-05 06:22:19 +00:00
|
|
|
using System.Linq;
|
2021-07-22 21:12:27 +00:00
|
|
|
using System.Reflection;
|
2021-08-05 06:22:19 +00:00
|
|
|
using System.Text;
|
2021-07-22 21:12:27 +00:00
|
|
|
using System.Text.RegularExpressions;
|
|
|
|
using System.Threading.Tasks;
|
2021-08-05 06:22:19 +00:00
|
|
|
using Microsoft.CodeAnalysis.CSharp;
|
2021-07-22 21:12:27 +00:00
|
|
|
using Microsoft.Extensions.Configuration;
|
|
|
|
using Microsoft.Extensions.Logging;
|
2021-08-07 22:20:46 +00:00
|
|
|
using Microsoft.VisualStudio.Web.CodeGeneration;
|
2021-08-05 06:22:19 +00:00
|
|
|
using Props.Data;
|
2021-07-22 21:12:27 +00:00
|
|
|
using Props.Models.Search;
|
|
|
|
using Props.Options;
|
|
|
|
using Props.Shop.Framework;
|
|
|
|
|
|
|
|
namespace Props.Services.Modules
|
|
|
|
{
|
2021-08-05 06:22:19 +00:00
|
|
|
public class ModularShopManager : IShopManager
|
2021-07-22 21:12:27 +00:00
|
|
|
{
|
2021-08-07 22:20:46 +00:00
|
|
|
private ILoggerFactory loggerFactory;
|
2021-08-05 06:22:19 +00:00
|
|
|
private ILogger<ModularShopManager> logger;
|
2021-07-22 21:12:27 +00:00
|
|
|
private Dictionary<string, IShop> shops;
|
|
|
|
private ModulesOptions options;
|
|
|
|
private IConfiguration configuration;
|
2021-08-05 06:22:19 +00:00
|
|
|
private bool disposedValue;
|
|
|
|
|
2021-08-07 22:20:46 +00:00
|
|
|
public ModularShopManager(IConfiguration configuration, ILogger<ModularShopManager> logger, ILoggerFactory loggerFactory)
|
2021-07-22 21:12:27 +00:00
|
|
|
{
|
2021-08-07 22:20:46 +00:00
|
|
|
this.loggerFactory = loggerFactory;
|
2021-07-22 21:12:27 +00:00
|
|
|
this.logger = logger;
|
2021-08-07 22:20:46 +00:00
|
|
|
this.configuration = configuration;
|
2021-07-22 21:12:27 +00:00
|
|
|
options = configuration.GetSection(ModulesOptions.Modules).Get<ModulesOptions>();
|
2021-08-07 22:20:46 +00:00
|
|
|
Directory.CreateDirectory(options.ModuleDataDir);
|
2021-07-22 21:12:27 +00:00
|
|
|
shops = new Dictionary<string, IShop>();
|
2021-08-07 22:20:46 +00:00
|
|
|
LoadShops();
|
2021-07-22 21:12:27 +00:00
|
|
|
}
|
|
|
|
|
2021-08-05 06:22:19 +00:00
|
|
|
public IEnumerable<string> GetAllShopNames()
|
2021-07-22 21:12:27 +00:00
|
|
|
{
|
|
|
|
return shops.Keys;
|
|
|
|
}
|
|
|
|
|
2021-08-05 06:22:19 +00:00
|
|
|
|
|
|
|
public IShop GetShop(string name)
|
2021-07-22 21:12:27 +00:00
|
|
|
{
|
2021-08-05 06:22:19 +00:00
|
|
|
return shops[name];
|
|
|
|
}
|
|
|
|
|
|
|
|
public IEnumerable<IShop> GetAllShops()
|
|
|
|
{
|
|
|
|
return shops.Values;
|
2021-07-22 21:12:27 +00:00
|
|
|
}
|
|
|
|
|
2021-08-07 22:20:46 +00:00
|
|
|
public void LoadShops()
|
2021-07-22 21:12:27 +00:00
|
|
|
{
|
2021-08-07 22:20:46 +00:00
|
|
|
string shopsDir = options.ModulesDir;
|
|
|
|
string shopRegex = options.ShopRegex;
|
|
|
|
bool recursiveLoad = options.RecursiveLoad;
|
|
|
|
|
2021-07-22 21:12:27 +00:00
|
|
|
Stack<string> directories = new Stack<string>();
|
|
|
|
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)
|
|
|
|
{
|
2021-08-09 18:32:16 +00:00
|
|
|
DirectoryInfo dataDir = Directory.CreateDirectory(Path.Combine(options.ModuleDataDir, file.Substring(file.IndexOf(Path.DirectorySeparatorChar) + 1)));
|
|
|
|
logger.LogDebug("Checking data directory for \"{0}\" at \"{1}\"", Path.GetFileName(file), dataDir.FullName);
|
2021-08-07 22:20:46 +00:00
|
|
|
shop.Initialize(dataDir.FullName, loggerFactory);
|
2021-07-22 21:12:27 +00:00
|
|
|
success += 1;
|
2021-08-07 22:20:46 +00:00
|
|
|
if (!shops.TryAdd(shop.ShopName, shop))
|
|
|
|
{
|
|
|
|
logger.LogWarning("Duplicate shop {0} detected. Ignoring the latter.", shop.ShopName);
|
|
|
|
}
|
2021-08-05 06:22:19 +00:00
|
|
|
logger.LogDebug("Loaded \"{0}\".", shop.ShopName);
|
2021-07-22 21:12:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (success == 0)
|
|
|
|
{
|
|
|
|
logger.LogWarning("There were no shops found within the assembly at path \"{0}\".", file);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-08-05 06:22:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
protected virtual void Dispose(bool disposing)
|
|
|
|
{
|
|
|
|
if (!disposedValue)
|
|
|
|
{
|
|
|
|
if (disposing)
|
|
|
|
{
|
|
|
|
foreach (string shopName in shops.Keys)
|
|
|
|
{
|
2021-08-09 18:32:16 +00:00
|
|
|
shops[shopName].SaveData().AsTask().Wait();
|
2021-08-05 06:22:19 +00:00
|
|
|
shops[shopName].Dispose();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
disposedValue = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void Dispose()
|
|
|
|
{
|
|
|
|
Dispose(disposing: true);
|
|
|
|
GC.SuppressFinalize(this);
|
2021-07-22 21:12:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|