Beispiel #1
0
        public void Build(Action <ContainerRegistrar> action, ConfigurationStore configStore)
        {
            var builder = new ContainerRegistrar();

            builder.RegisterComponents(Lifetime.Scoped, Assembly.GetExecutingAssembly());
            builder.RegisterService(CreateConnection, Lifetime.Scoped);
            builder.RegisterService(CreateTaskInvoker, Lifetime.Singleton);
            builder.RegisterInstance(Startup.ConnectionFactory);
            action(builder);

            RegisterBuiltInComponents(builder);
            RegisterQueues(builder);

            builder.RegisterService(x => Container, Lifetime.Singleton);
            builder.RegisterService(x => x);
            builder.RegisterConcrete <AnalysisDbContext>();
            builder.RegisterInstance(configStore);
            builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
            builder.RegisterControllers(Assembly.GetExecutingAssembly());

            var ioc = builder.Build();

            DependencyResolver.SetResolver(new GriffinDependencyResolver(ioc));
            GlobalConfiguration.Configuration.DependencyResolver = new GriffinWebApiDependencyResolver2(ioc);
            Container = new GriffinContainerAdapter(ioc);
        }
        public void Build(Action <ContainerRegistrar> action)
        {
            var builder = new ContainerRegistrar();

            builder.RegisterComponents(Lifetime.Scoped, Assembly.GetExecutingAssembly());
            builder.RegisterService(CreateConnection, Lifetime.Scoped);
            builder.RegisterService(CreateTaskInvoker, Lifetime.Singleton);
            action(builder);

            builder.RegisterComponents(Lifetime.Scoped, typeof(ValidateNewLoginHandler).Assembly);
            builder.RegisterComponents(Lifetime.Scoped, typeof(UserRepository).Assembly);
            builder.RegisterComponents(Lifetime.Scoped, typeof(ScanForNewErrorReports).Assembly);
            builder.RegisterComponents(Lifetime.Scoped, typeof(QueueProvider).Assembly);

            builder.RegisterService <IContainer>(x => Container, Lifetime.Singleton);
            builder.RegisterService <IServiceLocator>(x => x);

            builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
            builder.RegisterControllers(Assembly.GetExecutingAssembly());

            var ioc = builder.Build();

            DependencyResolver.SetResolver(new GriffinDependencyResolver(ioc));
            GlobalConfiguration.Configuration.DependencyResolver = new GriffinWebApiDependencyResolver2(ioc);
            Container = new GriffinContainerAdapter(ioc);
        }
        public void Build(Action <ContainerRegistrar> action, ConfigurationStore configStore)
        {
            var builder = new ContainerRegistrar();

            //need to invoke first to allow plug-ins to override default behavior.
            action(builder);

            builder.RegisterComponents(Lifetime.Scoped, Assembly.GetExecutingAssembly());
            builder.RegisterService(CreateUnitOfWork, Lifetime.Scoped);
            builder.RegisterService(CreateTaskInvoker, Lifetime.Singleton);

            RegisterBuiltInComponents(builder);
            RegisterQueues(builder);

            builder.RegisterService(x => Container, Lifetime.Singleton);
            builder.RegisterService(x => x);
            builder.RegisterConcrete <AnalysisDbContext>();
            builder.RegisterInstance(configStore);
            builder.RegisterType(typeof(IConfiguration <>), typeof(ConfigWrapper <>), Lifetime.Transient);
            builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
            builder.RegisterControllers(Assembly.GetExecutingAssembly());

            builder.RegisterService(x => configStore.Load <BaseConfiguration>());
            var ioc = builder.Build();

            DependencyResolver.SetResolver(new GriffinDependencyResolver(ioc));
            GlobalConfiguration.Configuration.DependencyResolver = new GriffinWebApiDependencyResolver2(ioc);
            Container = new GriffinContainerAdapter(ioc);
        }
Beispiel #4
0
        public void should_Be_able_To_Register_a_service_using_a_factory_method()
        {
            var reg = new ContainerRegistrar();

            reg.RegisterService(CreateFirstService, Lifetime.Scoped);
            reg.RegisterService(CreateMyService, Lifetime.Singleton);

            var container = reg.Build();
            var actual    = container.Resolve <ISomeServiceInterface>();

            Assert.NotNull(actual);
        }
        public void TestDelegateFactory()
        {
            var registrar = new ContainerRegistrar();

            registrar.RegisterService <MySelf>(ctnr => new MySelf(), Lifetime.Transient);
            registrar.RegisterConcrete <OneDepencency>(Lifetime.Singleton);
            var container = registrar.Build();

            container.Resolve <OneDepencency>();
        }
Beispiel #6
0
        public void Register(Func <object> factory, Type serviceType, string contract = null)
        {
            if (!string.IsNullOrEmpty(contract))
            {
                throw new NotSupportedException();
            }

            _registrar.RegisterService(serviceType, (c) => factory(), Lifetime.Transient);
            _container = _registrar.Build();
        }
Beispiel #7
0
        static void Main(string[] args)
        {
            var registrar = new ContainerRegistrar(Lifetime.Transient);
            registrar.RegisterComponents(Lifetime.Transient, Assembly.GetExecutingAssembly());
            registrar.RegisterService<ICommandDispatcher>(f => new ContainerDispatcher(f));
            var container = registrar.Build();

            var cmd = new CreateUser("arne", "King Arne");

            // the exception is thrown on purpose, read it.
            container.Resolve<ICommandDispatcher>().Dispatch(cmd);
        }
Beispiel #8
0
        private static void Main(string[] args)
        {
            var registrar = new ContainerRegistrar();
            registrar.RegisterComponents(Lifetime.Scoped, Assembly.GetExecutingAssembly());
            registrar.RegisterService<ICommandDispatcher>(x => new ContainerDispatcher(x), Lifetime.Scoped);
            var container = registrar.Build();

            using (var scope = container.CreateChildContainer())
            {
                var createUser = new CreateUser("arne", "Arne Eriksson");
                scope.Resolve<ICommandDispatcher>().Dispatch(createUser);
            }

            Console.WriteLine("Press enter to quit");
            Console.ReadLine();
        }
Beispiel #9
0
        private static void Main(string[] args)
        {
            var registrar = new ContainerRegistrar();

            registrar.RegisterComponents(Lifetime.Scoped, Assembly.GetExecutingAssembly());
            registrar.RegisterService <ICommandDispatcher>(x => new ContainerDispatcher(x), Lifetime.Scoped);
            var container = registrar.Build();

            using (var scope = container.CreateChildContainer())
            {
                var createUser = new CreateUser("arne", "Arne Eriksson");
                scope.Resolve <ICommandDispatcher>().Dispatch(createUser);
            }

            Console.WriteLine("Press enter to quit");
            Console.ReadLine();
        }
 private static void RegisterPropertyInjection(ContainerRegistrar registrar)
 {
     registrar.RegisterType <IServiceA, ServiceA>(Lifetime.Singleton);
     registrar.RegisterType <IServiceB, ServiceB>(Lifetime.Singleton);
     registrar.RegisterType <IServiceC, ServiceC>(Lifetime.Singleton);
     registrar.RegisterService <ISubObjectA>(x => new SubObjectA {
         ServiceA = x.Resolve <IServiceA>()
     }, Lifetime.Transient);
     registrar.RegisterService <ISubObjectB>(x => new SubObjectB {
         ServiceB = x.Resolve <IServiceB>()
     }, Lifetime.Transient);
     registrar.RegisterService <ISubObjectC>(x => new SubObjectC {
         ServiceC = x.Resolve <IServiceC>()
     }, Lifetime.Transient);
     registrar.RegisterService <IComplexPropertyObject1>(
         x => new ComplexPropertyObject1
     {
         ServiceA   = x.Resolve <IServiceA>(),
         ServiceB   = x.Resolve <IServiceB>(),
         ServiceC   = x.Resolve <IServiceC>(),
         SubObjectA = x.Resolve <ISubObjectA>(),
         SubObjectB = x.Resolve <ISubObjectB>(),
         SubObjectC = x.Resolve <ISubObjectC>()
     },
         Lifetime.Transient);
     registrar.RegisterService <IComplexPropertyObject2>(
         x => new ComplexPropertyObject2
     {
         ServiceA   = x.Resolve <IServiceA>(),
         ServiceB   = x.Resolve <IServiceB>(),
         ServiceC   = x.Resolve <IServiceC>(),
         SubObjectA = x.Resolve <ISubObjectA>(),
         SubObjectB = x.Resolve <ISubObjectB>(),
         SubObjectC = x.Resolve <ISubObjectC>()
     },
         Lifetime.Transient);
     registrar.RegisterService <IComplexPropertyObject3>(
         x => new ComplexPropertyObject3
     {
         ServiceA   = x.Resolve <IServiceA>(),
         ServiceB   = x.Resolve <IServiceB>(),
         ServiceC   = x.Resolve <IServiceC>(),
         SubObjectA = x.Resolve <ISubObjectA>(),
         SubObjectB = x.Resolve <ISubObjectB>(),
         SubObjectC = x.Resolve <ISubObjectC>()
     },
         Lifetime.Transient);
 }
        public void TestDelegateFactory()
        {
            var registrar = new ContainerRegistrar();
            registrar.RegisterService<MySelf>(ctnr => new MySelf(), Lifetime.Transient);
            registrar.RegisterConcrete<OneDepencency>(Lifetime.Singleton);
            var container = registrar.Build();

            container.Resolve<OneDepencency>();
        }
 private static void RegisterPropertyInjection(ContainerRegistrar registrar)
 {
     registrar.RegisterType<IServiceA, ServiceA>(Lifetime.Singleton);
     registrar.RegisterType<IServiceB, ServiceB>(Lifetime.Singleton);
     registrar.RegisterType<IServiceC, ServiceC>(Lifetime.Singleton);
     registrar.RegisterService<ISubObjectA>(x => new SubObjectA { ServiceA = x.Resolve<IServiceA>() }, Lifetime.Transient);
     registrar.RegisterService<ISubObjectB>(x => new SubObjectB { ServiceB = x.Resolve<IServiceB>() }, Lifetime.Transient);
     registrar.RegisterService<ISubObjectC>(x => new SubObjectC { ServiceC = x.Resolve<IServiceC>() }, Lifetime.Transient);
     registrar.RegisterService<IComplexPropertyObject1>(
         x => new ComplexPropertyObject1
         {
             ServiceA = x.Resolve<IServiceA>(),
             ServiceB = x.Resolve<IServiceB>(),
             ServiceC = x.Resolve<IServiceC>(),
             SubObjectA = x.Resolve<ISubObjectA>(),
             SubObjectB = x.Resolve<ISubObjectB>(),
             SubObjectC = x.Resolve<ISubObjectC>()
         },
         Lifetime.Transient);
     registrar.RegisterService<IComplexPropertyObject2>(
         x => new ComplexPropertyObject2
         {
             ServiceA = x.Resolve<IServiceA>(),
             ServiceB = x.Resolve<IServiceB>(),
             ServiceC = x.Resolve<IServiceC>(),
             SubObjectA = x.Resolve<ISubObjectA>(),
             SubObjectB = x.Resolve<ISubObjectB>(),
             SubObjectC = x.Resolve<ISubObjectC>()
         },
         Lifetime.Transient);
     registrar.RegisterService<IComplexPropertyObject3>(
         x => new ComplexPropertyObject3
         {
             ServiceA = x.Resolve<IServiceA>(),
             ServiceB = x.Resolve<IServiceB>(),
             ServiceC = x.Resolve<IServiceC>(),
             SubObjectA = x.Resolve<ISubObjectA>(),
             SubObjectB = x.Resolve<ISubObjectB>(),
             SubObjectC = x.Resolve<ISubObjectC>()
         },
         Lifetime.Transient);
 }
Beispiel #13
0
        private async void Startup()
        {
            // Print exception messages in English
            Thread.CurrentThread.CurrentUICulture     = CultureInfo.InvariantCulture;
            CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.InvariantCulture;

            // Set the AppDomain working directory to the current resource root
            Environment.CurrentDirectory = Path.GetFullPath(API.GetResourcePath(API.GetCurrentResourceName()));

            new Logger().Info($"NFive {typeof(Program).Assembly.GetCustomAttributes<AssemblyInformationalVersionAttribute>().First().InformationalVersion}");

            // TODO: Check and warn if local CitizenFX.Core.Server.dll is found

            var config = ConfigurationManager.Load <CoreConfiguration>("core.yml");

            // Use configured culture for output
            Thread.CurrentThread.CurrentCulture     = config.Locale.Culture.First();
            CultureInfo.DefaultThreadCurrentCulture = config.Locale.Culture.First();

            ServerConfiguration.Locale    = config.Locale;
            ServerLogConfiguration.Output = config.Log.Output;

            var logger = new Logger(config.Log.Core);

            API.SetGameType(config.Display.Game);
            API.SetMapName(config.Display.Map);

            // Setup RPC handlers
            RpcManager.Configure(config.Log.Comms, this.EventHandlers, this.Players);

            var events = new EventManager(config.Log.Comms);
            var comms  = new CommunicationManager(events);
            var rcon   = new RconManager(comms);

            // Load core controllers
            try
            {
                var dbController = new DatabaseController(new Logger(config.Log.Core, "Database"), ConfigurationManager.Load <DatabaseConfiguration>("database.yml"), comms);
                await dbController.Loaded();

                this.controllers.Add(new Name("NFive/Database"), new List <Controller> {
                    dbController
                });
            }
            catch (Exception ex)
            {
                logger.Error(ex, "Database connection error");
                logger.Warn("Fatal error, exiting");
                Environment.Exit(1);
            }

            var eventController = new EventController(new Logger(config.Log.Core, "FiveM"), comms);
            await eventController.Loaded();

            this.controllers.Add(new Name("NFive/RawEvents"), new List <Controller> {
                eventController
            });

            var sessionController = new SessionController(new Logger(config.Log.Core, "Session"), ConfigurationManager.Load <SessionConfiguration>("session.yml"), comms);
            await sessionController.Loaded();

            this.controllers.Add(new Name("NFive/Session"), new List <Controller> {
                sessionController
            });

            // Resolve dependencies
            var graph = DefinitionGraph.Load();

            // IoC
            var assemblies = new List <Assembly>();

            assemblies.AddRange(graph.Plugins.Where(p => p.Server?.Include != null).SelectMany(p => p.Server.Include.Select(i => Assembly.LoadFrom(Path.Combine("plugins", p.Name.Vendor, p.Name.Project, $"{i}.net.dll")))));
            assemblies.AddRange(graph.Plugins.Where(p => p.Server?.Main != null).SelectMany(p => p.Server.Main.Select(m => Assembly.LoadFrom(Path.Combine("plugins", p.Name.Vendor, p.Name.Project, $"{m}.net.dll")))));

            var registrar = new ContainerRegistrar();

            registrar.RegisterService <ILogger>(s => new Logger());
            registrar.RegisterInstance <IRconManager>(rcon);
            registrar.RegisterInstance <IBaseScriptProxy>(new BaseScriptProxy(this.EventHandlers, this.Exports, this.Players));
            registrar.RegisterInstance <ICommunicationManager>(comms);
            registrar.RegisterInstance <IClientList>(new ClientList(new Logger(config.Log.Core, "ClientList"), comms));
            registrar.RegisterPluginComponents(assemblies.Distinct());

            // DI
            var container = registrar.Build();

            var pluginDefaultLogLevel = config.Log.Plugins.ContainsKey("default") ? config.Log.Plugins["default"] : LogLevel.Info;

            // Load plugins into the AppDomain
            foreach (var plugin in graph.Plugins)
            {
                logger.Info($"Loading {plugin.FullName}");

                // Load include files
                foreach (var includeName in plugin.Server?.Include ?? new List <string>())
                {
                    var includeFile = Path.Combine("plugins", plugin.Name.Vendor, plugin.Name.Project, $"{includeName}.net.dll");
                    if (!File.Exists(includeFile))
                    {
                        throw new FileNotFoundException(includeFile);
                    }

                    AppDomain.CurrentDomain.Load(File.ReadAllBytes(includeFile));
                }

                // Load main files
                foreach (var mainName in plugin.Server?.Main ?? new List <string>())
                {
                    var mainFile = Path.Combine("plugins", plugin.Name.Vendor, plugin.Name.Project, $"{mainName}.net.dll");
                    if (!File.Exists(mainFile))
                    {
                        throw new FileNotFoundException(mainFile);
                    }

                    var asm = Assembly.LoadFrom(mainFile);

                    var sdkVersion = asm.GetCustomAttribute <ServerPluginAttribute>();

                    if (sdkVersion == null)
                    {
                        throw new Exception("Unable to load outdated SDK plugin");                         // TODO
                    }

                    if (sdkVersion.Target != SDK.Server.SDK.Version)
                    {
                        throw new Exception("Unable to load outdated SDK plugin");
                    }

                    var types = Assembly.LoadFrom(mainFile).GetTypes().Where(t => !t.IsAbstract && t.IsClass).ToList();

                    // Find migrations
                    foreach (var migrationType in types.Where(t => t.BaseType != null && t.BaseType.IsGenericType && t.BaseType.GetGenericTypeDefinition() == typeof(MigrationConfiguration <>)))
                    {
                        var configuration = (DbMigrationsConfiguration)Activator.CreateInstance(migrationType);
                        var migrator      = new DbMigrator(configuration);

                        if (!migrator.GetPendingMigrations().Any())
                        {
                            continue;
                        }

                        if (!ServerConfiguration.AutomaticMigrations)
                        {
                            throw new MigrationsPendingException($"Plugin {plugin.FullName} has pending migrations but automatic migrations are disabled");
                        }

                        foreach (var migration in migrator.GetPendingMigrations())
                        {
                            new Logger(config.Log.Core, "Database").Debug($"[{mainName}] Running migration: {migration}");

                            migrator.Update(migration);
                        }
                    }

                    // Find controllers
                    foreach (var controllerType in types.Where(t => t.IsSubclassOf(typeof(Controller)) || t.IsSubclassOf(typeof(ConfigurableController <>))))
                    {
                        var logLevel = config.Log.Plugins.ContainsKey(plugin.Name) ? config.Log.Plugins[plugin.Name] : pluginDefaultLogLevel;

                        var constructorArgs = new List <object>
                        {
                            new Logger(logLevel, plugin.Name)
                        };

                        // Check if controller is configurable
                        if (controllerType.BaseType != null && controllerType.BaseType.IsGenericType && controllerType.BaseType.GetGenericTypeDefinition() == typeof(ConfigurableController <>))
                        {
                            // Initialize the controller configuration
                            constructorArgs.Add(ConfigurationManager.InitializeConfig(plugin.Name, controllerType.BaseType.GetGenericArguments()[0]));
                        }

                        // Resolve IoC arguments
                        constructorArgs.AddRange(controllerType.GetConstructors()[0].GetParameters().Skip(constructorArgs.Count).Select(p => container.Resolve(p.ParameterType)));

                        Controller controller = null;

                        try
                        {
                            // Construct controller instance
                            controller = (Controller)Activator.CreateInstance(controllerType, constructorArgs.ToArray());
                        }
                        catch (Exception ex)
                        {
                            // TODO: Dispose of controller

                            logger.Error(ex, $"Unhandled exception in plugin {plugin.FullName}");
                        }

                        if (controller == null)
                        {
                            continue;
                        }

                        try
                        {
                            await controller.Loaded();

                            if (!this.controllers.ContainsKey(plugin.Name))
                            {
                                this.controllers.Add(plugin.Name, new List <Controller>());
                            }
                            this.controllers[plugin.Name].Add(controller);
                        }
                        catch (Exception ex)
                        {
                            // TODO: Dispose of controller

                            logger.Error(ex, $"Unhandled exception loading plugin {plugin.FullName}");
                        }
                    }
                }
            }

            await Task.WhenAll(this.controllers.SelectMany(c => c.Value).Select(s => s.Started()));

            rcon.Controllers = this.controllers;

            comms.Event(CoreEvents.ClientPlugins).FromClients().OnRequest(e => e.Reply(graph.Plugins));

            logger.Debug($"{graph.Plugins.Count.ToString(CultureInfo.InvariantCulture)} plugin(s) loaded, {this.controllers.Count.ToString(CultureInfo.InvariantCulture)} controller(s) created");

            comms.Event(ServerEvents.ServerInitialized).ToServer().Emit();

            logger.Info("Server ready");
        }
Beispiel #14
0
        private async void Startup()
        {
            // Set the AppDomain working directory to the current resource root
            Environment.CurrentDirectory = Path.GetFullPath(API.GetResourcePath(API.GetCurrentResourceName()));

            Logger.Initialize();
            new Logger().Info($"NFive {typeof(Program).Assembly.GetCustomAttributes<AssemblyInformationalVersionAttribute>().First().InformationalVersion}");

            var config = ConfigurationManager.Load <CoreConfiguration>("nfive.yml");

            ServerLogConfiguration.Output = config.Log.Output;
            //ServerConfiguration.LogLevel = config.Log.Level;

            var logger = new Logger(config.Log.Core);

            API.SetGameType(config.Display.Game);
            API.SetMapName(config.Display.Map);

            // Setup RPC handlers
            RpcManager.Configure(config.Log.Rpc, this.EventHandlers);

            // Client log mirroring
            new RpcHandler().Event("nfive:log:mirror").On(new Action <IRpcEvent, DateTime, LogLevel, string, string>((e, dt, level, prefix, message) =>
            {
                new Logger(LogLevel.Trace, $"Client#{e.Client.Handle}|{prefix}").Log(message, level);
            }));

            var events = new EventManager(config.Log.Events);
            var rcon   = new RconManager(new RpcHandler());

            // Load core controllers
            var dbController = new DatabaseController(new Logger(config.Log.Core, "Database"), events, new RpcHandler(), rcon, ConfigurationManager.Load <DatabaseConfiguration>("database.yml"));
            await dbController.Loaded();

            this.controllers.Add(new Name("NFive/Database"), new List <Controller> {
                dbController
            });

            var sessionController = new SessionController(new Logger(config.Log.Core, "Session"), events, new RpcHandler(), rcon, ConfigurationManager.Load <SessionConfiguration>("session.yml"));
            await sessionController.Loaded();

            this.controllers.Add(new Name("NFive/Session"), new List <Controller> {
                sessionController
            });

            // Resolve dependencies
            var graph = DefinitionGraph.Load();

            var pluginDefaultLogLevel = config.Log.Plugins.ContainsKey("default") ? config.Log.Plugins["default"] : LogLevel.Info;

            // IoC
            var assemblies = new List <Assembly>();

            assemblies.AddRange(graph.Plugins.Where(p => p.Server?.Include != null).SelectMany(p => p.Server.Include.Select(i => Assembly.LoadFrom(Path.Combine("plugins", p.Name.Vendor, p.Name.Project, $"{i}.net.dll")))));
            assemblies.AddRange(graph.Plugins.Where(p => p.Server?.Main != null).SelectMany(p => p.Server.Main.Select(m => Assembly.LoadFrom(Path.Combine("plugins", p.Name.Vendor, p.Name.Project, $"{m}.net.dll")))));

            var registrar = new ContainerRegistrar();

            registrar.RegisterService <ILogger>(s => new Logger());
            registrar.RegisterType <IRpcHandler, RpcHandler>();
            registrar.RegisterInstance <IEventManager>(events);
            registrar.RegisterInstance <IRconManager>(rcon);
            registrar.RegisterInstance <IClientList>(new ClientList(new Logger(config.Log.Core, "ClientList"), new RpcHandler()));
            registrar.RegisterSdkComponents(assemblies.Distinct());

            // DI
            var container = registrar.Build();

            // Load plugins into the AppDomain
            foreach (var plugin in graph.Plugins)
            {
                logger.Info($"Loading {plugin.FullName}");

                // Load include files
                foreach (var includeName in plugin.Server?.Include ?? new List <string>())
                {
                    var includeFile = Path.Combine("plugins", plugin.Name.Vendor, plugin.Name.Project, $"{includeName}.net.dll");
                    if (!File.Exists(includeFile))
                    {
                        throw new FileNotFoundException(includeFile);
                    }

                    AppDomain.CurrentDomain.Load(File.ReadAllBytes(includeFile));
                }

                // Load main files
                foreach (var mainName in plugin.Server?.Main ?? new List <string>())
                {
                    var mainFile = Path.Combine("plugins", plugin.Name.Vendor, plugin.Name.Project, $"{mainName}.net.dll");
                    if (!File.Exists(mainFile))
                    {
                        throw new FileNotFoundException(mainFile);
                    }

                    var types = Assembly.LoadFrom(mainFile).GetTypes().Where(t => !t.IsAbstract && t.IsClass).ToList();

                    // Find migrations
                    foreach (var migrationType in types.Where(t => t.BaseType != null && t.BaseType.IsGenericType && t.BaseType.GetGenericTypeDefinition() == typeof(MigrationConfiguration <>)))
                    {
                        var configuration = (DbMigrationsConfiguration)Activator.CreateInstance(migrationType);
                        var migrator      = new DbMigrator(configuration);

                        if (!migrator.GetPendingMigrations().Any())
                        {
                            continue;
                        }

                        if (!ServerConfiguration.AutomaticMigrations)
                        {
                            throw new MigrationsPendingException($"Plugin {plugin.FullName} has pending migrations but automatic migrations are disabled");
                        }

                        foreach (var migration in migrator.GetPendingMigrations())
                        {
                            new Logger(config.Log.Core, "Database").Debug($"[{mainName}] Running migration: {migration}");

                            migrator.Update(migration);
                        }
                    }

                    // Find controllers
                    foreach (var controllerType in types.Where(t => t.IsSubclassOf(typeof(Controller)) || t.IsSubclassOf(typeof(ConfigurableController <>))))
                    {
                        var logLevel = config.Log.Plugins.ContainsKey(plugin.Name) ? config.Log.Plugins[plugin.Name] : pluginDefaultLogLevel;

                        var constructorArgs = new List <object>
                        {
                            new Logger(logLevel, plugin.Name),
                            events,
                            new RpcHandler(),
                            rcon
                        };

                        // Check if controller is configurable
                        if (controllerType.BaseType != null && controllerType.BaseType.IsGenericType && controllerType.BaseType.GetGenericTypeDefinition() == typeof(ConfigurableController <>))
                        {
                            // Initialize the controller configuration
                            constructorArgs.Add(ConfigurationManager.InitializeConfig(plugin.Name, controllerType.BaseType.GetGenericArguments()[0]));
                        }

                        // Resolve IoC arguments
                        constructorArgs.AddRange(controllerType.GetConstructors()[0].GetParameters().Skip(constructorArgs.Count).Select(p => container.Resolve(p.ParameterType)));

                        Controller controller = null;

                        try
                        {
                            // Construct controller instance
                            controller = (Controller)Activator.CreateInstance(controllerType, constructorArgs.ToArray());
                        }
                        catch (Exception ex)
                        {
                            // TODO: Dispose of controller

                            logger.Error(ex, $"Unhandled exception in plugin {plugin.FullName}");
                        }

                        if (controller == null)
                        {
                            continue;
                        }

                        try
                        {
                            await controller.Loaded();

                            if (!this.controllers.ContainsKey(plugin.Name))
                            {
                                this.controllers.Add(plugin.Name, new List <Controller>());
                            }
                            this.controllers[plugin.Name].Add(controller);
                        }
                        catch (Exception ex)
                        {
                            // TODO: Dispose of controller

                            logger.Error(ex, $"Unhandled exception loading plugin {plugin.FullName}");
                        }
                    }
                }
            }

#pragma warning disable 4014
            foreach (var controller in this.controllers.SelectMany(c => c.Value))
            {
                controller.Started();
            }
#pragma warning restore 4014

            rcon.Controllers = this.controllers;

            new RpcHandler().Event(SDK.Core.Rpc.RpcEvents.ClientPlugins).On(e => e.Reply(graph.Plugins));

            events.Raise(ServerEvents.ServerInitialized);

            logger.Debug($"{graph.Plugins.Count} plugin(s) loaded, {this.controllers.Count} controller(s) created");
        }