131 lines
4.3 KiB
C#
131 lines
4.3 KiB
C#
using SQLLinter.Common;
|
||
using SQLLinter.Common.Helpers;
|
||
using SQLLinter.Core.Interfaces;
|
||
using SQLLinter.Infrastructure.Parser;
|
||
|
||
namespace SQLLinter.Infrastructure.Plugins
|
||
{
|
||
public class PluginHandler : IPluginHandler
|
||
{
|
||
private readonly IConfig _config;
|
||
private readonly IAssemblyWrapper _assemblyWrapper;
|
||
private readonly IReporter _reporter;
|
||
private readonly IFileversionWrapper _versionWrapper;
|
||
|
||
private List<Type> _ruleTypes = new();
|
||
private Dictionary<string, IRule> _rules = new();
|
||
|
||
public IList<IRule> Rules => _rules.Values.ToList();
|
||
|
||
public IDictionary<string, IRule> RuleWithNames => _rules;
|
||
|
||
public PluginHandler(IReporter reporter, IConfig config)
|
||
: this(reporter, new AssemblyWrapper(), new VersionInfoWrapper(), config) { }
|
||
|
||
public PluginHandler(
|
||
IReporter reporter,
|
||
IAssemblyWrapper assemblyWrapper,
|
||
IFileversionWrapper versionWrapper,
|
||
IConfig config
|
||
)
|
||
{
|
||
this._reporter = reporter;
|
||
this._assemblyWrapper = assemblyWrapper;
|
||
this._versionWrapper = versionWrapper;
|
||
this._config = config;
|
||
|
||
LoadDefaultRules();
|
||
LoadPlugins();
|
||
}
|
||
|
||
private void ActivatePlugin(Type type)
|
||
{
|
||
var instance = (IRule?)Activator.CreateInstance(type);
|
||
|
||
if (instance == null)
|
||
{
|
||
_reporter.Report($"Ошибка создания экземпляра правила '{type.FullName}'");
|
||
return;
|
||
}
|
||
|
||
var ruleName = instance.Name;
|
||
|
||
if (_config.Rules.TryGetValue(ruleName, out var severity))
|
||
{
|
||
instance.Severity = severity;
|
||
}
|
||
|
||
if (instance.Severity == RuleViolationSeverity.Off)
|
||
{
|
||
_reporter.Report($"Правило '{ruleName}' выключено");
|
||
return;
|
||
}
|
||
|
||
if (_rules.ContainsKey(ruleName))
|
||
{
|
||
_reporter.Report($"Ошибка добавления правила '{type.FullName}': правило '{ruleName}' уже создано");
|
||
return;
|
||
}
|
||
|
||
_rules.Add(ruleName, instance);
|
||
|
||
_reporter.Report($"Правило '{ruleName}' ({instance.Severity}) добавлено с типом '{type.FullName}'");
|
||
}
|
||
|
||
private void LoadDefaultRules()
|
||
{
|
||
//Загрузка дефолтных правил
|
||
var defaultRuleTypes = RuleVisitorFriendlyNameTypeMap.DefaultRuleTypes;
|
||
defaultRuleTypes.ForEach(AddRuleType);
|
||
}
|
||
|
||
private void AddRuleType(Type ruleType)
|
||
{
|
||
if (_ruleTypes.Contains(ruleType))
|
||
{
|
||
_reporter.Report($"Уже загружено правило '{ruleType.FullName}'");
|
||
return;
|
||
}
|
||
|
||
_ruleTypes.Add(ruleType);
|
||
_reporter.Report($"Добавлено правило '{ruleType.FullName}'");
|
||
|
||
ActivatePlugin(ruleType);
|
||
}
|
||
|
||
private void LoadPlugins()
|
||
{
|
||
var paths = FileHelpers.FindFilesWithMask(_config.Plugins);
|
||
|
||
//Загрузка плагинов
|
||
foreach (var path in paths)
|
||
{
|
||
if (!File.Exists(path))
|
||
{
|
||
_reporter.Report($"Ошибка загрузки плагина '{path}': Файл не найден.");
|
||
}
|
||
else if (Path.GetExtension(path)?.ToLower() != "dll")
|
||
{
|
||
_reporter.Report($"Ошибка загрузки плагина '{path}': Неподдерживаемый формат файла. Ожидается файл с расширением .dll.");
|
||
}
|
||
else
|
||
{
|
||
LoadPlugin(path);
|
||
}
|
||
}
|
||
}
|
||
|
||
private void LoadPlugin(string path)
|
||
{
|
||
var dll = _assemblyWrapper.LoadFrom(path);
|
||
var version = _versionWrapper.GetVersion(dll);
|
||
|
||
foreach (var type in _assemblyWrapper.GetExportedTypes(dll))
|
||
{
|
||
var rules = RuleVisitorFriendlyNameTypeMap.GetRuleTypes(dll);
|
||
rules.ForEach(AddRuleType);
|
||
}
|
||
}
|
||
}
|
||
}
|