using System; using System.Linq; using System.Reflection; using Artemis.Core.DryIoc.Factories; using Artemis.Core.Providers; using Artemis.Core.Services; using Artemis.Storage; using Artemis.Storage.Migrations; using Artemis.Storage.Repositories.Interfaces; using DryIoc; namespace Artemis.Core.DryIoc; /// /// Provides an extension method to register services onto a DryIoc . /// public static class ContainerExtensions { /// /// Registers core services into the container. /// /// The builder building the current container public static void RegisterCore(this IContainer container) { Assembly[] coreAssembly = {typeof(IArtemisService).Assembly}; Assembly[] storageAssembly = {typeof(IRepository).Assembly}; // Bind all services as singletons container.RegisterMany(coreAssembly, type => type.IsAssignableTo(), Reuse.Singleton); container.RegisterMany(coreAssembly, type => type.IsAssignableTo(), Reuse.Singleton, setup: Setup.With(condition: HasAccessToProtectedService)); // Bind storage container.RegisterDelegate(() => StorageManager.CreateRepository(Constants.DataFolder), Reuse.Singleton); container.Register(Reuse.Singleton); container.RegisterMany(storageAssembly, type => type.IsAssignableTo(), Reuse.Singleton); // Bind migrations container.RegisterMany(storageAssembly, type => type.IsAssignableTo(), Reuse.Singleton, nonPublicServiceTypes: true); container.RegisterMany(storageAssembly, type => type.IsAssignableTo(), Reuse.Singleton, nonPublicServiceTypes: true); container.RegisterMany(coreAssembly, type => type.IsAssignableTo(), Reuse.Singleton); container.Register(Reuse.Singleton); container.Register(Made.Of(_ => ServiceInfo.Of(), f => f.CreatePluginSettings(Arg.Index(0)), r => r.Parent.ImplementationType)); container.Register(Reuse.Singleton); container.Register(Made.Of(_ => ServiceInfo.Of(), f => f.CreateLogger(Arg.Index(0)), r => r.Parent.ImplementationType)); } /// /// Registers plugin services into the container, this is typically a child container. /// /// The builder building the current container /// The plugin to register public static void RegisterPlugin(this IContainer container, Plugin plugin) { container.RegisterInstance(plugin, setup: Setup.With(preventDisposal: true)); // Bind plugin service interfaces, DryIoc expects at least one match when calling RegisterMany so ensure there is something to register first if (plugin.Assembly != null && plugin.Assembly.GetTypes().Any(t => t.IsAssignableTo())) container.RegisterMany(new[] {plugin.Assembly}, type => type.IsAssignableTo(), Reuse.Singleton, ifAlreadyRegistered: IfAlreadyRegistered.Keep); } private static bool HasAccessToProtectedService(Request request) { // Plugin assembly locations may not be set for some reason, that case it's also not allowed >:( return request.Parent.ImplementationType != null && !string.IsNullOrWhiteSpace(request.Parent.ImplementationType.Assembly.Location) && !request.Parent.ImplementationType.Assembly.Location.StartsWith(Constants.PluginsFolder); } }