using System; using Artemis.Core.Services; using Ninject.Extensions.Conventions; using Ninject.Modules; using Ninject.Planning.Bindings.Resolvers; namespace Artemis.Core.Ninject { internal class PluginModule : NinjectModule { public PluginModule(Plugin plugin) { Plugin = plugin ?? throw new ArgumentNullException(nameof(plugin)); } public Plugin Plugin { get; } public override void Load() { if (Kernel == null) throw new ArtemisCoreException("Failed to bind plugin child module, kernel is null."); Kernel.Components.Remove(); Kernel.Bind().ToConstant(Plugin); // Bind plugin service interfaces Kernel.Bind(x => { x.From(Plugin.Assembly) .IncludingNonPublicTypes() .SelectAllClasses() .InheritedFrom() .BindAllInterfaces() .Configure(c => c.InSingletonScope()); }); // Plugin developers may not use an interface so bind the plugin services to themselves // Sadly if they do both, the kernel will treat the interface and the base type as two different singletons // perhaps we can avoid that, but I'm not sure how Kernel.Bind(x => { x.From(Plugin.Assembly) .IncludingNonPublicTypes() .SelectAllClasses() .InheritedFrom() .BindToSelf() .Configure(c => c.InSingletonScope()); }); } } }