removed async methods, for some reason just results in null.. no exceptions anywhere :(

added protection to prevent reloading assemblies already in the domain.
corrected bug only identifying INotifierProviderFactory types.
This commit is contained in:
chris.watts90@outlook.com 2017-06-23 22:56:23 +01:00
commit 17d50b5be1
17 changed files with 192 additions and 57 deletions

View File

@ -2,6 +2,6 @@
{ {
public interface INotifierProviderFactory public interface INotifierProviderFactory
{ {
INotifierProvider CreateProvider(); INotifierProvider GetProvider();
} }
} }

View File

@ -0,0 +1,7 @@
namespace Interfaces
{
public interface ISystemControl
{
void Shutdown();
}
}

View File

@ -0,0 +1,10 @@
using System.Collections.Generic;
namespace Interfaces
{
public interface ISystemControlManager
{
List<string> GetAvailableProviders();
void Shutdown();
}
}

View File

@ -0,0 +1,7 @@
namespace Interfaces
{
public interface ISystemControlProviderFactory
{
ISystemControl GetProvider();
}
}

View File

@ -0,0 +1,7 @@
namespace Interfaces
{
public interface ITransponderUtilities
{
int GetLastScannedIdAsync();
}
}

View File

@ -0,0 +1,7 @@
namespace Interfaces
{
public interface ITransponderUtilityProviderFactory
{
ITransponderUtilities GetProvider();
}
}

View File

@ -50,6 +50,11 @@
<Compile Include="INotifierManager.cs" /> <Compile Include="INotifierManager.cs" />
<Compile Include="INotifierProvider.cs" /> <Compile Include="INotifierProvider.cs" />
<Compile Include="INotifierProviderFactory.cs" /> <Compile Include="INotifierProviderFactory.cs" />
<Compile Include="ISystemControl.cs" />
<Compile Include="ISystemControlManager.cs" />
<Compile Include="ISystemControlProviderFactory.cs" />
<Compile Include="ITransponderUtilities.cs" />
<Compile Include="ITransponderUtilityProviderFactory.cs" />
<Compile Include="NotificationEventArgs.cs" /> <Compile Include="NotificationEventArgs.cs" />
<Compile Include="Pilot.cs" /> <Compile Include="Pilot.cs" />
<Compile Include="ProviderDetails.cs" /> <Compile Include="ProviderDetails.cs" />

View File

@ -0,0 +1,21 @@
using System.Diagnostics;
using Interfaces;
namespace IrDaemonNotifier
{
public class IrDaemonController:ISystemControl
{
public void Shutdown()
{
Debug.WriteLine("test");
}
}
public class IrDaemonControllerProviderFactory : ISystemControlProviderFactory
{
public ISystemControl GetProvider()
{
return new IrDaemonController();
}
}
}

View File

@ -40,6 +40,7 @@
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="IrDaemonController.cs" />
<Compile Include="IrDaemonNotifier.cs" /> <Compile Include="IrDaemonNotifier.cs" />
<Compile Include="IrDaemonNotifierProviderFactory.cs" /> <Compile Include="IrDaemonNotifierProviderFactory.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />

View File

@ -15,7 +15,7 @@ namespace IrDaemonNotifier
{ {
_logger = logger; _logger = logger;
} }
public INotifierProvider CreateProvider() public INotifierProvider GetProvider()
{ {
return new IrDaemonNotifier(_logger); return new IrDaemonNotifier(_logger);
} }

View File

@ -1,5 +1,4 @@
using System.Diagnostics; using System.IO;
using System.IO;
using Interfaces; using Interfaces;
using Nancy; using Nancy;
using Nancy.Authentication.Forms; using Nancy.Authentication.Forms;
@ -7,11 +6,10 @@ using Nancy.Bootstrapper;
using Nancy.Bootstrappers.Ninject; using Nancy.Bootstrappers.Ninject;
using Nancy.Conventions; using Nancy.Conventions;
using Nancy.Diagnostics; using Nancy.Diagnostics;
using Nancy.TinyIoc;
using Ninject; using Ninject;
using RaceLapTimer.ApiControllers;
using RaceLapTimer.Extensions; using RaceLapTimer.Extensions;
using RaceLapTimer.Extensions.Notifications; using RaceLapTimer.Extensions.Notifications;
using RaceLapTimer.Extensions.SystemControl;
namespace RaceLapTimer namespace RaceLapTimer
{ {
@ -39,10 +37,10 @@ namespace RaceLapTimer
container.Load(cfgFilePath); container.Load(cfgFilePath);
container.Bind<INotifierManager>().To<NotificationManager>().InSingletonScope(); container.Bind<INotifierManager>().To<NotificationManager>().InSingletonScope();
container.Bind<ISystemControlManager>().To<SystemControlManager>().InSingletonScope();
//var nM = container.Get<INotifierManager>(); var sM = container.Get<ISystemControlManager>();
//nM.NotifyRaceStarted(new NotificationEventArgs()); sM.Shutdown();
} }
protected override void ConfigureRequestContainer(IKernel container, NancyContext context) protected override void ConfigureRequestContainer(IKernel container, NancyContext context)

View File

@ -3,11 +3,11 @@ using System.Collections.Generic;
using Interfaces; using Interfaces;
using Ninject; using Ninject;
namespace RaceLapTimer.Extensions.Notifications namespace RaceLapTimer.Extensions
{ {
class ContainerHelper : IContainerHelper class ContainerHelper : IContainerHelper
{ {
private IKernel _container; private readonly IKernel _container;
public ContainerHelper(IKernel container) public ContainerHelper(IKernel container)
{ {
_container = container; _container = container;

View File

@ -1,9 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO;
using System.Linq; using System.Linq;
using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
using Interfaces; using Interfaces;
@ -18,13 +16,13 @@ namespace RaceLapTimer.Extensions.Notifications
RegisterProviders(locator); RegisterProviders(locator);
} }
private async void RegisterProviders(IPluginLocator locator) private void RegisterProviders(IPluginLocator locator)
{ {
var providerFactories = await locator.LocateAsync<INotifierProviderFactory>(); var providerFactories = locator.Locate<INotifierProviderFactory>();
_providers = new List<INotifierProvider>(); _providers = new List<INotifierProvider>();
foreach (var factory in providerFactories) foreach (var factory in providerFactories)
{ {
_providers.Add(factory.CreateProvider()); _providers.Add(factory.GetProvider());
} }
} }

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
@ -13,11 +14,13 @@ namespace RaceLapTimer.Extensions
{ {
private readonly IContainerHelper _helper; private readonly IContainerHelper _helper;
private readonly IPluginPathProvider _pluginPath; private readonly IPluginPathProvider _pluginPath;
private readonly ILoggerService _logger;
public PluginLocator(IContainerHelper helper, IPluginPathProvider pluginPath) public PluginLocator(IContainerHelper helper, IPluginPathProvider pluginPath, ILoggerService logger)
{ {
_helper = helper; _helper = helper;
_pluginPath = pluginPath; _pluginPath = pluginPath;
_logger = logger;
} }
public async Task<List<T>> LocateAsync<T>() public async Task<List<T>> LocateAsync<T>()
@ -27,48 +30,71 @@ namespace RaceLapTimer.Extensions
public List<T> Locate<T>() public List<T> Locate<T>()
{ {
if (!Directory.Exists(_pluginPath.GetPluginPath)) return new List<T>(); try
var files = Directory.GetFiles(_pluginPath.GetPluginPath);
var discoveryList = new List<DiscoveredPlugin>();
foreach (var file in files)
{ {
var ext = Path.GetExtension(file); if (!Directory.Exists(_pluginPath.GetPluginPath)) return new List<T>();
if (!IsAssembly(ext)) continue; var files = Directory.GetFiles(_pluginPath.GetPluginPath);
var discoveryList = new List<DiscoveredPlugin>();
var assembly = Assembly.ReflectionOnlyLoadFrom(file); foreach (var file in files)
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 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 == typeof(T).Name)
select t).ToList();
if (pluginTypes.Any())
{ {
FilePath = file, discoveryList.Add(new DiscoveredPlugin
PluginType = pluginTypes.First(), {
TypeToBindTo = typeof(INotifierProviderFactory), FilePath = file,
UniqueName = Path.GetFileNameWithoutExtension(file) PluginType = pluginTypes.First(),
}); TypeToBindTo = typeof(T),
UniqueName = Path.GetFileNameWithoutExtension(file)
});
}
} }
}
foreach (var plugin in discoveryList) foreach (var plugin in discoveryList)
{
var assy = AssemblyIsLoaded(plugin.FilePath)
? GetAssemblyFromAppDomain(plugin.FilePath)
: 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<T>().ToList();
}
catch (Exception ex)
{ {
//load into the appDomain.. _logger.Error(ex);
var assy = Assembly.LoadFrom(plugin.FilePath); return new List<T>();
//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<T>().ToList(); private Assembly GetAssemblyFromAppDomain(string pluginFilePath)
{
var name = Path.GetFileName(pluginFilePath);
return AppDomain.CurrentDomain.GetAssemblies().First(x => x.ManifestModule.Name == name);
}
private bool AssemblyIsLoaded(string pluginFilePath)
{
var name = Path.GetFileName(pluginFilePath);
var d = AppDomain.CurrentDomain.GetAssemblies().Where(x => x.ManifestModule.Name == name);
return d.Any();
} }
private bool IsAssembly(string extension) private bool IsAssembly(string extension)
@ -78,11 +104,7 @@ namespace RaceLapTimer.Extensions
"dll", "exe" "dll", "exe"
}; };
var ext = extension.Remove(0, 1); var ext = extension.Remove(0, 1);
if (validAssemblyExts.Contains(ext)) return validAssemblyExts.Contains(ext);
{
return true;
}
return false;
} }
private class DiscoveredPlugin private class DiscoveredPlugin

View File

@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Interfaces;
namespace RaceLapTimer.Extensions.SystemControl
{
class SystemControlManager : ISystemControlManager
{
private List<ISystemControl> _providers;
private readonly ILoggerService _logger;
public SystemControlManager(IPluginLocator locator, ILoggerService logger)
{
RegisterProviders(locator);
_logger = logger;
}
private void RegisterProviders(IPluginLocator locator)
{
try
{
var providerFactories = locator.Locate<ISystemControlProviderFactory>();
_providers = new List<ISystemControl>();
foreach (var factory in providerFactories)
{
_providers.Add(factory.GetProvider());
}
}
catch (Exception ex)
{
_logger.Error(ex);
}
}
public List<string> GetAvailableProviders()
{
return _providers.Select(x=>x.GetType().ToString()).ToList();
}
public void Shutdown()
{
foreach (var provider in _providers)
{
Task.Factory.StartNew(() => provider.Shutdown());
}
}
}
}

View File

@ -115,6 +115,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Extensions\PluginLocator.cs" /> <Compile Include="Extensions\PluginLocator.cs" />
<Compile Include="Extensions\SystemControl\SystemControlManager.cs" />
<Compile Include="IDbProvider.cs" /> <Compile Include="IDbProvider.cs" />
<Compile Include="ApiControllers\LapTrackApiModule.cs" /> <Compile Include="ApiControllers\LapTrackApiModule.cs" />
<Compile Include="ApiControllers\MonitorApiModule.cs" /> <Compile Include="ApiControllers\MonitorApiModule.cs" />
@ -126,7 +127,7 @@
<Compile Include="TestProvider.cs" /> <Compile Include="TestProvider.cs" />
<Compile Include="AuthenticationBootstrapper.cs" /> <Compile Include="AuthenticationBootstrapper.cs" />
<Compile Include="ConfigFilePathProvider.cs" /> <Compile Include="ConfigFilePathProvider.cs" />
<Compile Include="Extensions\Notifications\ContainerHelper.cs" /> <Compile Include="Extensions\ContainerHelper.cs" />
<Compile Include="Extensions\Notifications\NotificationManager.cs" /> <Compile Include="Extensions\Notifications\NotificationManager.cs" />
<Compile Include="Modules\HistoryModule.cs" /> <Compile Include="Modules\HistoryModule.cs" />
<Compile Include="ApiControllers\InfoApiModule.cs" /> <Compile Include="ApiControllers\InfoApiModule.cs" />

View File

@ -15,7 +15,7 @@ namespace UdpNotifier
_logger = logger; _logger = logger;
} }
public INotifierProvider CreateProvider() public INotifierProvider GetProvider()
{ {
return new UdpNotifierProvider(_logger); return new UdpNotifierProvider(_logger);
} }