diff --git a/.gitignore b/.gitignore index 1747694..850cb05 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ **/.vs/** **dotsettings **.DotSettings.user +**/.localhistory/** diff --git a/RaceLapTimer/Interfaces/IPluginLocator.cs b/RaceLapTimer/Interfaces/IPluginLocator.cs new file mode 100644 index 0000000..8904315 --- /dev/null +++ b/RaceLapTimer/Interfaces/IPluginLocator.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Interfaces +{ + public interface IPluginLocator + { + List Locate(); + } +} diff --git a/RaceLapTimer/Interfaces/Interfaces.csproj b/RaceLapTimer/Interfaces/Interfaces.csproj index cff9079..2ff5ad6 100644 --- a/RaceLapTimer/Interfaces/Interfaces.csproj +++ b/RaceLapTimer/Interfaces/Interfaces.csproj @@ -43,6 +43,7 @@ + diff --git a/RaceLapTimer/RaceLapTimer/AuthenticationBootstrapper.cs b/RaceLapTimer/RaceLapTimer/AuthenticationBootstrapper.cs index 64bcf19..1916af9 100644 --- a/RaceLapTimer/RaceLapTimer/AuthenticationBootstrapper.cs +++ b/RaceLapTimer/RaceLapTimer/AuthenticationBootstrapper.cs @@ -10,6 +10,7 @@ using Nancy.Diagnostics; using Nancy.TinyIoc; using Ninject; using RaceLapTimer.ApiControllers; +using RaceLapTimer.Extensions; using RaceLapTimer.Extensions.Notifications; namespace RaceLapTimer @@ -30,14 +31,16 @@ namespace RaceLapTimer container.Bind().To(); container.Bind().To(); container.Bind().To(); - container.Bind().To().InSingletonScope(); container.Bind().To().InSingletonScope(); - + container.Bind().To(); //load dynamic plugins..: var cfgFilePath = Path.Combine(container.Get().GetPath, "NinjectConfig.xml"); container.Load(cfgFilePath); + container.Bind().To().InSingletonScope(); + + var nM = container.Get(); nM.NotifyRaceStarted(new NotificationEventArgs()); } diff --git a/RaceLapTimer/RaceLapTimer/Extensions/Notifications/NotificationManager.cs b/RaceLapTimer/RaceLapTimer/Extensions/Notifications/NotificationManager.cs index 1fec36b..f3989b8 100644 --- a/RaceLapTimer/RaceLapTimer/Extensions/Notifications/NotificationManager.cs +++ b/RaceLapTimer/RaceLapTimer/Extensions/Notifications/NotificationManager.cs @@ -4,8 +4,6 @@ using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; -using System.Security.Cryptography.X509Certificates; -using System.Text; using System.Threading.Tasks; using Interfaces; @@ -14,27 +12,11 @@ namespace RaceLapTimer.Extensions.Notifications class NotificationManager : INotifierManager { private readonly List _providers; - public NotificationManager(IPluginPathProvider pluginPath, IContainerHelper helper) + public NotificationManager(IPluginPathProvider pluginPath, IContainerHelper helper, IPluginLocator locator) { - if (!Directory.Exists(pluginPath.GetPluginPath)) return; - var files = Directory.GetFiles(pluginPath.GetPluginPath); - - foreach (var file in files) - { - var ext = Path.GetExtension(file); - if (!IsAssembly(ext)) continue; - - var assembly = Assembly.LoadFrom(file); //need to use ReflectionOnlyLoadFrom rather than LoadFrom here, this will cause exception if another extension point is implemented - var pluginTypes = (from t in assembly.GetExportedTypes() - where t.GetInterfaces().Any(x=>x.Name==nameof(INotifierProviderFactory)) - select t).ToList(); - if (pluginTypes.Any()) - { - helper.RegisterType(typeof(INotifierProviderFactory), pluginTypes.First(), Path.GetFileNameWithoutExtension(file)); - } - } - - var providerFactories = helper.GetAll().ToList(); + var providerFactories = locator.Locate(); + + //var providerFactories = helper.GetAll().ToList(); _providers = new List(); foreach (var factory in providerFactories) { @@ -108,5 +90,13 @@ namespace RaceLapTimer.Extensions.Notifications } return false; } + + private class DiscoveredPlugin + { + public string FilePath { get; set; } + public Type PluginType { get; set; } + public Type TypeToBindTo { get; set; } + public string UniqueName { get; set; } + } } } diff --git a/RaceLapTimer/RaceLapTimer/Extensions/PluginLocator.cs b/RaceLapTimer/RaceLapTimer/Extensions/PluginLocator.cs new file mode 100644 index 0000000..a2be69c --- /dev/null +++ b/RaceLapTimer/RaceLapTimer/Extensions/PluginLocator.cs @@ -0,0 +1,96 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using Interfaces; + +namespace RaceLapTimer.Extensions +{ + public class PluginLocator:IPluginLocator + { + private readonly IContainerHelper _helper; + private readonly IPluginPathProvider _pluginPath; + + public PluginLocator(IContainerHelper helper, IPluginPathProvider pluginPath) + { + _helper = helper; + _pluginPath = pluginPath; + } + + public async Task> LocateAsync() + { + return await Task.Run(()=> Locate()); + } + + private List Locate() + { + if (!Directory.Exists(_pluginPath.GetPluginPath)) return new List(); + var files = Directory.GetFiles(_pluginPath.GetPluginPath); + var discoveryList = new List(); + + foreach (var file in files) + { + var ext = Path.GetExtension(file); + if (!IsAssembly(ext)) continue; + + var assembly = Assembly.ReflectionOnlyLoadFrom(file); + var pluginTypes = (from t in assembly.GetExportedTypes() + where t.GetInterfaces().Any(x => x.Name == nameof(INotifierProviderFactory)) + select t).ToList(); + if (pluginTypes.Any()) + { + discoveryList.Add(new DiscoveredPlugin + { + FilePath = file, + PluginType = pluginTypes.First(), + TypeToBindTo = typeof(INotifierProviderFactory), + UniqueName = Path.GetFileNameWithoutExtension(file) + }); + } + } + + foreach (var plugin in discoveryList) + { + //load into the appDomain.. + var assy = Assembly.LoadFrom(plugin.FilePath); + //register our type + var pluginTypes = + (from t in assy.GetExportedTypes() + where t.GetInterfaces().Any(x => x.Name == plugin.TypeToBindTo.Name) + select t).ToList(); + + if (!pluginTypes.Any()) continue; + + var pg = pluginTypes.First(); + _helper.RegisterType(plugin.TypeToBindTo, pg, plugin.UniqueName); + } + + return _helper.GetAll().ToList(); + } + + private bool IsAssembly(string extension) + { + var validAssemblyExts = new List + { + "dll", "exe" + }; + var ext = extension.Remove(0, 1); + if (validAssemblyExts.Contains(ext)) + { + return true; + } + return false; + } + + private class DiscoveredPlugin + { + public string FilePath { get; set; } + public Type PluginType { get; set; } + public Type TypeToBindTo { get; set; } + public string UniqueName { get; set; } + } + } +} diff --git a/RaceLapTimer/RaceLapTimer/RaceLapTimer.csproj b/RaceLapTimer/RaceLapTimer/RaceLapTimer.csproj index 2188153..27fe674 100644 --- a/RaceLapTimer/RaceLapTimer/RaceLapTimer.csproj +++ b/RaceLapTimer/RaceLapTimer/RaceLapTimer.csproj @@ -114,6 +114,7 @@ + diff --git a/RaceLapTimer/RaceLapTimerHost/RaceLapTimerHost.csproj b/RaceLapTimer/RaceLapTimerHost/RaceLapTimerHost.csproj index 4523aff..6021921 100644 --- a/RaceLapTimer/RaceLapTimerHost/RaceLapTimerHost.csproj +++ b/RaceLapTimer/RaceLapTimerHost/RaceLapTimerHost.csproj @@ -72,10 +72,6 @@ - - {916994f6-1711-4aeb-8de6-4ab6fcb3f080} - IrDaemonNotifier - {9a93a12f-7591-406a-a4f3-41aa8299c4b4} NLogLogger @@ -84,10 +80,6 @@ {85A3CC28-096C-40A6-8C67-3AADE40EDF32} RaceLapTimer - - {734097b0-a764-40ad-957a-43fe4f085b65} - UdpNotifier -