protected virtual IServiceProvider GetServiceProvider(IPluginBootstrapper bootstrapper) { var hostServices = this.sharedServicesProvider.ProvideHostServices(); var sharedServices = this.sharedServicesProvider.ProvideSharedServices(); var allServices = new ServiceCollection(); foreach (var service in hostServices) { allServices.Add(service); } foreach (var service in sharedServices) { allServices.Add(service); } if (bootstrapper != null) { sharedServices = bootstrapper.Bootstrap(allServices); } allServices.AddScoped <IPluginServiceProvider>(sp => new DefaultPluginServiceProvider( sp, hostServices.Select(d => d.ServiceType), sharedServices.Select(d => d.ServiceType) )); return(allServices.BuildServiceProvider()); }
public object CreateRemoteInstance(Type pluginType, IPluginBootstrapper bootstrapper, MethodInfo factoryMethod, Assembly assembly) { var contructors = pluginType.GetConstructors(BindingFlags.Public | BindingFlags.Instance); if (contructors.Count() > 1) { throw new PrisePluginException($"Multiple public constructors found for remote plugin {pluginType.Name}"); } var firstCtor = contructors.FirstOrDefault(); if (firstCtor != null && !firstCtor.GetParameters().Any()) { return(assembly.CreateInstance(pluginType.FullName)); } if (factoryMethod == null) { throw new PrisePluginException($@"Plugins must either provide a default parameterless constructor or implement a static factory method. Like; 'public static {pluginType.Name} CreatePlugin(IServiceProvider serviceProvider)"); } var sharedServices = this.sharedServicesProvider.ProvideSharedServices(); if (bootstrapper != null) { sharedServices = bootstrapper.Bootstrap(sharedServices); } var serviceProvider = sharedServices.BuildServiceProvider(); return(factoryMethod.Invoke(null, new[] { serviceProvider })); }
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 Task <T> ActivatePlugin <T>(IPluginActivationOptions pluginActivationOptions) { if (pluginActivationOptions.PluginAssembly == null) { throw new ArgumentNullException($"{nameof(IPluginActivationOptions)}.{nameof(pluginActivationOptions.PluginAssembly)}"); } if (pluginActivationOptions.PluginType == null) { throw new ArgumentNullException($"{nameof(IPluginActivationOptions)}.{nameof(pluginActivationOptions.PluginType)}"); } if (pluginActivationOptions.ParameterConverter == null) { throw new ArgumentNullException($"{nameof(IPluginActivationOptions)}.{nameof(pluginActivationOptions.ParameterConverter)}"); } if (pluginActivationOptions.ResultConverter == null) { throw new ArgumentNullException($"{nameof(IPluginActivationOptions)}.{nameof(pluginActivationOptions.ResultConverter)}"); } T pluginProxy = default(T); IPluginBootstrapper bootstrapperProxy = null; var pluginActivationContext = this.pluginActivationContextProvider.ProvideActivationContext(pluginActivationOptions.PluginType, pluginActivationOptions.PluginAssembly); if (pluginActivationContext.PluginBootstrapperType != null) { var remoteBootstrapperInstance = this.remotePluginActivator.CreateRemoteBootstrapper(pluginActivationContext, pluginActivationOptions.HostServices); var remoteBootstrapperProxy = this.proxyCreator.CreateBootstrapperProxy(remoteBootstrapperInstance); this.disposables.Add(remoteBootstrapperProxy as IDisposable); bootstrapperProxy = remoteBootstrapperProxy; } var remoteObject = this.remotePluginActivator.CreateRemoteInstance( pluginActivationContext, bootstrapperProxy, pluginActivationOptions.HostServices ); pluginProxy = this.proxyCreator.CreatePluginProxy <T>(remoteObject, pluginActivationOptions.ParameterConverter, pluginActivationOptions.ResultConverter); this.disposables.Add(pluginProxy as IDisposable); return(Task.FromResult(pluginProxy)); }
public object Create(ControllerContext context) { var pluginLoadOptions = context.HttpContext.RequestServices.GetRequiredService <IPluginLoadOptions <T> >(); var cache = context.HttpContext.RequestServices.GetRequiredService <IPluginCache <T> >(); var controllerType = context.ActionDescriptor.ControllerTypeInfo.AsType(); foreach (var pluginAssembly in cache.GetAll()) { if (pluginAssembly.GetTypes().Any(t => t.Name == controllerType.Name)) { var pluginActivationContext = pluginLoadOptions.PluginActivationContextProvider.ProvideActivationContext(controllerType, pluginAssembly); IPluginBootstrapper bootstrapperProxy = null; if (pluginActivationContext.PluginBootstrapperType != null) { var remoteBootstrapperInstance = pluginLoadOptions.Activator.CreateRemoteBootstrapper(pluginActivationContext.PluginBootstrapperType, pluginAssembly); var remoteBootstrapperProxy = pluginLoadOptions.ProxyCreator.CreateBootstrapperProxy(remoteBootstrapperInstance); bootstrapperProxy = remoteBootstrapperProxy; } // This will use the parameterless ctor // But it should use the IFeatureServiceProvider from the IFeatureServiceCollection var remoteController = pluginLoadOptions.Activator.CreateRemoteInstance( pluginActivationContext, bootstrapperProxy); //TODO CHECK //controllerType, //pluginAssembly, //bootstrapperProxy, //pluginActivationContext.PluginFactoryMethod); // TODO Create own Controller Activator var controllerContext = new ControllerContext(); controllerContext.HttpContext = context.HttpContext; var controllerContextProperty = controllerType.GetProperty("ControllerContext"); controllerContextProperty.SetValue(remoteController, controllerContext); return(remoteController); } } // 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)); }
protected T[] CreatePluginInstances <T>(IPluginLoadOptions <T> pluginLoadOptions, ref Assembly pluginAssembly) { var pluginInstances = new List <T>(); var pluginTypes = pluginAssembly .GetTypes() .Where(t => t.CustomAttributes .Any(c => c.AttributeType.Name == typeof(Prise.Plugin.PluginAttribute).Name && (c.NamedArguments.First(a => a.MemberName == "PluginType").TypedValue.Value as Type).Name == typeof(T).Name)) .OrderBy(t => t.Name) .AsEnumerable(); if (pluginTypes == null || !pluginTypes.Any()) { throw new PrisePluginException($@"No plugin was found in assembly {pluginAssembly.FullName}. Requested plugin type: {typeof(T).Name}. Please add the {nameof(PluginAttribute)} to your plugin class and specify the PluginType: [Plugin(PluginType = typeof({typeof(T).Name}))]"); } pluginTypes = pluginLoadOptions.PluginSelector.SelectPlugins(pluginTypes); if (!pluginTypes.Any()) { throw new PrisePluginException($@"Selector returned no plugin for {pluginAssembly.FullName}. Requested plugin type: {typeof(T).Name}. Please add the {nameof(PluginAttribute)} to your plugin class and specify the PluginType: [Plugin(PluginType = typeof({typeof(T).Name}))]"); } foreach (var pluginType in pluginTypes) { var bootstrapperType = GetPluginBootstrapper(ref pluginAssembly, pluginType); var pluginFactoryMethod = GetPluginFactoryMethod(pluginType); IPluginBootstrapper bootstrapper = null; if (bootstrapperType != null) { var remoteBootstrapperInstance = pluginLoadOptions.Activator.CreateRemoteBootstrapper(bootstrapperType, pluginAssembly); var remoteBootstrapperProxy = pluginLoadOptions.ProxyCreator.CreateBootstrapperProxy(remoteBootstrapperInstance); this.disposables.Add(remoteBootstrapperProxy as IDisposable); bootstrapper = remoteBootstrapperProxy; } var remoteObject = pluginLoadOptions.Activator.CreateRemoteInstance(pluginType, bootstrapper, pluginFactoryMethod, pluginAssembly); var remoteProxy = pluginLoadOptions.ProxyCreator.CreatePluginProxy(remoteObject, pluginLoadOptions); this.disposables.Add(remoteProxy as IDisposable); pluginInstances.Add(remoteProxy); } return(pluginInstances.ToArray()); }
public virtual object CreateRemoteInstance(PluginActivationContext pluginActivationContext, IPluginBootstrapper bootstrapper = null) { var pluginType = pluginActivationContext.PluginType; var pluginAssembly = pluginActivationContext.PluginAssembly; var factoryMethod = pluginActivationContext.PluginFactoryMethod; var contructors = pluginType.GetConstructors(BindingFlags.Public | BindingFlags.Instance); if (contructors.Count() > 1) { throw new PrisePluginException($"Multiple public constructors found for remote plugin {pluginType.Name}"); } var serviceProvider = GetServiceProvider(bootstrapper); if (factoryMethod != null) { return(factoryMethod.Invoke(null, new[] { serviceProvider })); } var firstCtor = contructors.FirstOrDefault(); if (firstCtor != null && !firstCtor.GetParameters().Any()) // Empty default CTOR { var pluginServiceProvider = serviceProvider.GetService <IPluginServiceProvider>(); var remoteInstance = pluginAssembly.CreateInstance(pluginType.FullName); remoteInstance = InjectFieldsWithServices(remoteInstance, pluginServiceProvider, pluginActivationContext.PluginServices); ActivateIfNecessary(remoteInstance, pluginActivationContext); return(remoteInstance); } throw new PrisePluginException($"Plugin of type {typeof(T).Name} could not be activated."); }
protected T[] CreatePluginInstances <T>(IPluginLoadOptions <T> pluginLoadOptions, ref Assembly pluginAssembly) { var pluginInstances = new List <T>(); var pluginTypes = pluginLoadOptions.PluginTypesProvider.ProvidePluginTypes(pluginAssembly); if (pluginTypes == null || !pluginTypes.Any()) { throw new PrisePluginException($@"No plugin was found in assembly {pluginAssembly.FullName}. Requested plugin type: {typeof(T).Name}. Please add the {nameof(PluginAttribute)} to your plugin class and specify the PluginType: [Plugin(PluginType = typeof({typeof(T).Name}))]"); } foreach (var type in pluginTypes) { pluginLoadOptions.Logger.PluginTypeProvided(type); } pluginTypes = pluginLoadOptions.PluginSelector.SelectPlugins(pluginTypes); if (!pluginTypes.Any()) { throw new PrisePluginException($@"Selector returned no plugin for {pluginAssembly.FullName}. Requested plugin type: {typeof(T).Name}. Please add the {nameof(PluginAttribute)} to your plugin class and specify the PluginType: [Plugin(PluginType = typeof({typeof(T).Name}))]"); } foreach (var type in pluginTypes) { pluginLoadOptions.Logger.PluginTypeSelected(type); } foreach (var pluginType in pluginTypes) { T pluginProxy = default(T); IPluginBootstrapper bootstrapperProxy = null; var pluginActivationContext = pluginLoadOptions.PluginActivationContextProvider.ProvideActivationContext(pluginType, pluginAssembly); pluginLoadOptions.Logger.PluginActivationContextProvided(pluginActivationContext); if (pluginActivationContext.PluginBootstrapperType != null) { var remoteBootstrapperInstance = pluginLoadOptions.Activator.CreateRemoteBootstrapper(pluginActivationContext.PluginBootstrapperType, pluginAssembly); pluginLoadOptions.Logger.RemoteBootstrapperActivated(remoteBootstrapperInstance); var remoteBootstrapperProxy = pluginLoadOptions.ProxyCreator.CreateBootstrapperProxy(remoteBootstrapperInstance); pluginLoadOptions.Logger.RemoteBootstrapperProxyCreated(remoteBootstrapperProxy); this.disposables.Add(remoteBootstrapperProxy as IDisposable); bootstrapperProxy = remoteBootstrapperProxy; } var remoteObject = pluginLoadOptions.Activator.CreateRemoteInstance( pluginActivationContext, bootstrapperProxy ); pluginLoadOptions.Logger.RemoteInstanceCreated(remoteObject); pluginProxy = pluginLoadOptions.ProxyCreator.CreatePluginProxy(remoteObject, pluginLoadOptions.ParameterConverter, pluginLoadOptions.ResultConverter); pluginLoadOptions.Logger.RemoteProxyCreated(pluginProxy); this.disposables.Add(pluginProxy as IDisposable); pluginInstances.Add(pluginProxy); } return(pluginInstances.ToArray()); }
protected virtual IServiceProvider GetServiceProviderForPlugin(IServiceCollection services, IPluginBootstrapper bootstrapper, IServiceCollection hostServices) { // Add all the host services to the main collection foreach (var service in hostServices) { services.Add(service); } IServiceCollection pluginServices = new ServiceCollection(); // If a bootstrapper was provided, add the services for the plugin to a new collection if (bootstrapper != null) { pluginServices = bootstrapper.Bootstrap(pluginServices); } // Add all the plugin services to the main collection foreach (var service in pluginServices) { services.Add(service); } services.AddScoped <IPluginServiceProvider>(sp => this.pluginServiceProviderFactory( sp, hostServices.Select(d => d.ServiceType), pluginServices.Select(d => d.ServiceType) )); return(services.BuildServiceProvider()); }
public void RemoteBootstrapperProxyCreated(IPluginBootstrapper bootstrapper) { Log($"Plugin<{this.pluginType}> bootstrapper proxy was created {bootstrapper.GetType().Name}"); }
public virtual object CreateRemoteInstance(PluginActivationContext pluginActivationContext, IPluginBootstrapper bootstrapper = null) { // TODO Check out RuntimeHelpers.GetUninitializedObject(pluginType); var pluginType = pluginActivationContext.PluginType; var pluginAssembly = pluginActivationContext.PluginAssembly; var factoryMethod = pluginActivationContext.PluginFactoryMethod; var contructors = pluginType.GetConstructors(BindingFlags.Public | BindingFlags.Instance); if (contructors.Count() > 1) { throw new PrisePluginException($"Multiple public constructors found for remote plugin {pluginType.Name}"); } var firstCtor = contructors.FirstOrDefault(); if (firstCtor != null && !firstCtor.GetParameters().Any()) { return(pluginAssembly.CreateInstance(pluginType.FullName)); } if (factoryMethod == null) { throw new PrisePluginException($@"Plugins must either provide a default parameterless constructor or implement a static factory method. Example; 'public static {pluginType.Name} CreatePlugin(IServiceProvider serviceProvider)"); } var hostServices = this.sharedServicesProvider.ProvideHostServices(); var sharedServices = this.sharedServicesProvider.ProvideSharedServices(); var allServices = new ServiceCollection(); foreach (var service in hostServices) { allServices.Add(service); } foreach (var service in sharedServices) { allServices.Add(service); } if (bootstrapper != null) { sharedServices = bootstrapper.Bootstrap(allServices); } allServices.AddScoped <IPluginServiceProvider>(sp => new DefaultPluginServiceProvider( sp, hostServices.Select(d => d.ServiceType), sharedServices.Select(d => d.ServiceType) )); var localProvider = allServices.BuildServiceProvider(); if (pluginActivationContext.PluginFactoryMethodWithPluginServiceProvider != null) { var factoryMethodWithPluginServiceProvider = pluginActivationContext.PluginFactoryMethodWithPluginServiceProvider; return(factoryMethodWithPluginServiceProvider.Invoke(null, new[] { localProvider.GetService(typeof(IPluginServiceProvider)) })); } return(factoryMethod.Invoke(null, new[] { localProvider })); }