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);
}
}