using System; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Threading.Tasks; using Artemis.Plugins.Exceptions; using Artemis.Plugins.Interfaces; using CSScriptLibrary; using Newtonsoft.Json; using Ninject; namespace Artemis.Plugins.Models { public class PluginInfo : IDisposable { /// /// The name of the plugin /// public string Name { get; set; } /// /// The version of the plugin /// public string Version { get; set; } /// /// The file implementing IPlugin, loaded on startup /// public string Main { get; set; } /// /// The file implementing IPluginViewModel, loaded when opened in the UI /// public string ViewModel { get; set; } /// /// The instantiated plugin, available after successful load /// [JsonIgnore] public IPlugin Plugin { get; set; } /// /// Full path to the plugin's current folder /// [JsonIgnore] public string Folder { get; set; } /// /// Indicates wether this is a built-in plugin. Built-in plugins are precompiled and have no files /// [JsonIgnore] public bool IsBuiltIn { get; private set; } public static async Task FromFolder(IKernel kernel, string folder) { if (!folder.EndsWith("\\")) folder += "\\"; if (!File.Exists(folder + "plugin.json")) throw new ArtemisPluginException(null, "Failed to load plugin, no plugin.json found in " + folder); var pluginInfo = JsonConvert.DeserializeObject(File.ReadAllText(folder + "plugin.json")); pluginInfo.Folder = folder; // Load the main script and get the type var assembly = await CSScript.Evaluator.CompileCodeAsync(File.ReadAllText(folder + pluginInfo.Main)); var pluginType = assembly.GetTypes().Where(t => typeof(IPlugin).IsAssignableFrom(t)).ToList(); if (!pluginType.Any()) throw new ArtemisPluginException(pluginInfo, "Failed to load plugin, no type found that implements IPlugin"); if (pluginType.Count > 1) throw new ArtemisPluginException(pluginInfo, "Failed to load plugin, more than one type found that implements IPlugin"); // Instantiate the plugin with Ninject pluginInfo.Plugin = (IPlugin) kernel.Get(pluginType.First()); pluginInfo.Plugin.LoadPlugin(); return pluginInfo; } public static PluginInfo FromBuiltInPlugin(IKernel kernel, IPlugin builtInPlugin) { var pluginInfo = new PluginInfo { Name = builtInPlugin.GetType().Name, Version = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).ProductVersion, Plugin = builtInPlugin, IsBuiltIn = true }; pluginInfo.Plugin.LoadPlugin(); return pluginInfo; } public void Dispose() { } public async Task GetModuleViewModel(IKernel kernel) { // Don't attempt to locave VMs for something other than a module if (Plugin is IModule) throw new ArtemisPluginException(this, "Cannot locate a view model for this plugin as it's not a module."); // Compile the ViewModel script and get the type var assembly = await CSScript.Evaluator.CompileCodeAsync(File.ReadAllText(Folder + ViewModel)); var vmType = assembly.GetTypes().Where(t => typeof(IModuleViewModel).IsAssignableFrom(t)).ToList(); if (!vmType.Any()) throw new ArtemisPluginException(this, "Failed to load plugin, no type found that implements IModuleViewModel"); if (vmType.Count > 1) throw new ArtemisPluginException(this, "Failed to load plugin, more than one type found that implements IModuleViewModel"); // Instantiate the ViewModel with Ninject var vm = (IModuleViewModel)kernel.Get(vmType.First()); vm.PluginInfo = this; return vm; } } }