pschelpdesk/Vendor/Prise.Mvc/DefaultPriseMvcControllerActivator.cs
2024-11-04 20:45:34 +01:00

77 lines
3.7 KiB
C#

using System;
using System.Linq;
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.Extensions.DependencyInjection;
using Prise.Activation;
using Prise.Infrastructure;
using Prise.Plugin;
using Prise.Proxy;
using Prise.Caching;
namespace Prise.Mvc
{
public class DefaultPriseMvcControllerActivator : IControllerActivator
{
public object Create(ControllerContext context)
{
var cache = context.HttpContext.RequestServices.GetRequiredService<IPluginCache>();
var controllerType = context.ActionDescriptor.ControllerTypeInfo.AsType();
foreach (var cachedPluginAssembly in cache.GetAll())
{
var pluginAssembly = cachedPluginAssembly.AssemblyShim.Assembly;
var pluginControllerType = pluginAssembly.GetTypes().FirstOrDefault(t => t.Name == controllerType.Name);
if (pluginControllerType != null)
{
var activatorContextProvider = context.HttpContext.RequestServices.GetRequiredService<IPluginActivationContextProvider>();
var remotePluginActivator = context.HttpContext.RequestServices.GetRequiredService<IRemotePluginActivator>();
var proxyCreator = context.HttpContext.RequestServices.GetRequiredService<IPluginProxyCreator>();
var resultConverter = context.HttpContext.RequestServices.GetRequiredService<IResultConverter>();
var parameterConverter = context.HttpContext.RequestServices.GetRequiredService<IParameterConverter>();
object controller = null;
IPluginBootstrapper bootstrapperProxy = null;
IServiceCollection hostServices = new ServiceCollection();
foreach (var hostServiceType in cachedPluginAssembly.HostTypes)
hostServices.Add(new ServiceDescriptor(hostServiceType, context.HttpContext.RequestServices.GetRequiredService(hostServiceType)));
var pluginActivationContext = activatorContextProvider.ProvideActivationContext(pluginControllerType, cachedPluginAssembly.AssemblyShim);
if (pluginActivationContext.PluginBootstrapperType != null)
{
var remoteBootstrapperInstance = remotePluginActivator.CreateRemoteBootstrapper(pluginActivationContext, hostServices);
var remoteBootstrapperProxy = proxyCreator.CreateBootstrapperProxy(remoteBootstrapperInstance);
bootstrapperProxy = remoteBootstrapperProxy;
}
controller = remotePluginActivator.CreateRemoteInstance(
pluginActivationContext,
bootstrapperProxy,
hostServices: hostServices
);
var controllerContext = new ControllerContext();
controllerContext.HttpContext = context.HttpContext;
var controllerContextProperty = controllerType.GetProperty("ControllerContext");
controllerContextProperty.SetValue(controller, controllerContext);
return controller;
}
}
// Use MSFT's own activator utilities to create a controller instance
// This avoids us to require to register all controllers as services
return ActivatorUtilities.CreateInstance(context.HttpContext.RequestServices, controllerType);
}
public void Release(ControllerContext context, object controller)
{
(controller as IDisposable)?.Dispose();
}
}
}