Esempio n. 1
0
        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 }));
        }
Esempio n. 3
0
        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));
        }
Esempio n. 4
0
        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));
        }
Esempio n. 6
0
        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());
        }
Esempio n. 7
0
        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.");
        }
Esempio n. 8
0
        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());
        }
Esempio n. 9
0
        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());
        }
Esempio n. 10
0
 public void RemoteBootstrapperProxyCreated(IPluginBootstrapper bootstrapper)
 {
     Log($"Plugin<{this.pluginType}> bootstrapper proxy was created {bootstrapper.GetType().Name}");
 }
Esempio n. 11
0
        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 }));
        }