207 lines
6.9 KiB
C#
207 lines
6.9 KiB
C#
namespace InspectionUI.ViewModels
|
|
{
|
|
using InspectionUI.Models;
|
|
|
|
using System;
|
|
using System.Collections.ObjectModel;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
|
|
public class PluginsVM : VM
|
|
{
|
|
const string Plugins = nameof(Plugins);
|
|
const string Abstraction = nameof(Abstraction);
|
|
|
|
private readonly FileSystemWatcher fileSystemWatcher;
|
|
private readonly DirectoryInfo pluginsDirectory;
|
|
private readonly string basePlugin;
|
|
|
|
public PluginsVM()
|
|
{
|
|
var pluginsPath = Path.Combine(Appsettings.CurrentDirectory, Plugins);
|
|
this.pluginsDirectory = Directory.CreateDirectory(pluginsPath);
|
|
this.basePlugin = Path.Combine(this.pluginsDirectory.Parent.FullName, $"{Plugins}.{Abstraction}.dll");
|
|
this.fileSystemWatcher = new FileSystemWatcher()
|
|
{
|
|
Path = this.pluginsDirectory.FullName,
|
|
EnableRaisingEvents = true,
|
|
Filter = $"{Plugins}.*.dll",
|
|
IncludeSubdirectories = false,
|
|
NotifyFilter = NotifyFilters.CreationTime
|
|
| NotifyFilters.FileName,
|
|
};
|
|
this.fileSystemWatcher.Created += this.FileSystemWatcher_PluginAdded;
|
|
this.fileSystemWatcher.Deleted += this.FileSystemWatcher_PluginDeleted;
|
|
this.fileSystemWatcher.Changed += this.FileSystemWatcher_PluginUpdated;
|
|
this.fileSystemWatcher.Renamed += this.FileSystemWatcher_PluginUpdated;
|
|
this.ItemsSource = new ObservableCollection<PluginVM>();
|
|
|
|
this.LoadExistingPlugins();
|
|
}
|
|
|
|
public ObservableCollection<PluginVM> ItemsSource { get; }
|
|
|
|
private void FileSystemWatcher_PluginAdded(object sender, FileSystemEventArgs args)
|
|
{
|
|
if (args.ChangeType == WatcherChangeTypes.Created)
|
|
{
|
|
var plugin = this.LoadPlugin(args.FullPath);
|
|
|
|
if (plugin != null)
|
|
{
|
|
this.DispatcherInvoke(() =>
|
|
{
|
|
this.ItemsSource.Add(plugin);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
private void FileSystemWatcher_PluginUpdated(object sender, FileSystemEventArgs args)
|
|
{
|
|
if (args.ChangeType == WatcherChangeTypes.Changed || args.ChangeType == WatcherChangeTypes.Renamed)
|
|
{
|
|
var plugin = this.LoadPlugin(args.FullPath);
|
|
|
|
if (plugin != null)
|
|
{
|
|
this.DispatcherInvoke(() =>
|
|
{
|
|
this.ItemsSource.Add(plugin);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
private void FileSystemWatcher_PluginDeleted(object sender, FileSystemEventArgs args)
|
|
{
|
|
if (args.ChangeType == WatcherChangeTypes.Deleted)
|
|
{
|
|
var plugin = this.ItemsSource.FirstOrDefault(x => x.Path == args.FullPath);
|
|
|
|
if (plugin != null)
|
|
{
|
|
this.DispatcherInvoke(() =>
|
|
{
|
|
this.ItemsSource.Remove(plugin);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
private void LoadExistingPlugins()
|
|
{
|
|
foreach (var fileInfo in this.pluginsDirectory.GetFiles())
|
|
{
|
|
if (fileInfo.Name.StartsWith(Plugins) && fileInfo.Extension.EndsWith("dll"))
|
|
{
|
|
var plugin = this.LoadPlugin(fileInfo.FullName);
|
|
|
|
if (plugin != null)
|
|
{
|
|
this.DispatcherInvoke(() =>
|
|
{
|
|
this.ItemsSource.Add(plugin);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private PluginVM LoadPlugin(string pluginDLL)
|
|
{
|
|
if (pluginDLL == this.basePlugin)
|
|
{
|
|
return default(PluginVM);
|
|
}
|
|
|
|
try
|
|
{
|
|
var domain = AppDomain.CreateDomain($"{Guid.NewGuid()}");
|
|
//var abstraction = domain.Load(new AssemblyName { CodeBase = this.basePlugin });
|
|
var plugin = domain.Load(new AssemblyName { CodeBase = pluginDLL });
|
|
var pluginAttributes = plugin.GetCustomAttributes(true);
|
|
var pluginVM = new PluginVM
|
|
{
|
|
Path = pluginDLL,
|
|
Version = plugin.GetName().Version.ToString()
|
|
};
|
|
var pluginVMProperties = typeof(PluginVM)
|
|
.GetProperties(BindingFlags.Public | BindingFlags.Instance);
|
|
|
|
foreach (var property in pluginVMProperties)
|
|
{
|
|
var propertyName = property.Name;
|
|
|
|
try
|
|
{
|
|
if (property.GetValue(pluginVM, null) is null)
|
|
{
|
|
foreach (var attribute in pluginAttributes)
|
|
{
|
|
var attributeType = attribute.GetType();
|
|
|
|
if (attributeType.Name == $"Assembly{propertyName}Attribute")
|
|
{
|
|
var attributeProperty = attributeType.GetProperty(propertyName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
|
|
|
|
if (attributeProperty != null)
|
|
{
|
|
var attributeValue = attributeType
|
|
.GetProperty(propertyName)
|
|
?.GetValue(attribute, null)
|
|
?.ToString();
|
|
|
|
property.SetValue(pluginVM, attributeValue, null);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception)
|
|
{
|
|
|
|
}
|
|
}
|
|
|
|
try
|
|
{
|
|
AppDomain.Unload(domain);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
|
|
}
|
|
|
|
return pluginVM;
|
|
}
|
|
catch (Exception)
|
|
{
|
|
return default(PluginVM);
|
|
}
|
|
}
|
|
}
|
|
|
|
public class PluginVM : VM
|
|
{
|
|
public string Path { get; set; }
|
|
|
|
public string Title { get; set; }
|
|
|
|
public string Description { get; set; }
|
|
|
|
public string Company { get; set; }
|
|
|
|
public string Product { get; set; }
|
|
|
|
public string Copyright { get; set; }
|
|
|
|
public string Trademark { get; set; }
|
|
|
|
public string Culture { get; set; }
|
|
|
|
public string Version { get; set; }
|
|
}
|
|
}
|