laatzen/Common/OmniPlus/InspectionUI/ViewModels/PluginsVM.cs
2024-04-05 09:52:44 +02:00

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; }
}
}