Skip to content

Commit

Permalink
Merge pull request #637 from riganti/iserviceprovider-injection-owin
Browse files Browse the repository at this point in the history
Added factory method for IServiceProvider on OWIN
  • Loading branch information
tomasherceg authored Aug 9, 2018
2 parents 73c90fc + eb8c0b8 commit 6b0fb38
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 12 deletions.
14 changes: 8 additions & 6 deletions src/DotVVM.Framework.Hosting.Owin/AppBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,12 @@ public static class AppBuilderExtensions
/// in production.
/// </param>
/// <param name="debug">A value indicating whether the application should run in debug mode.</param>
public static DotvvmConfiguration UseDotVVM<TStartup, TServiceConfigurator>(this IAppBuilder app, string applicationRootPath, bool useErrorPages = true, bool debug = true)
/// <param name="serviceProviderFactoryMethod">Register factory method to create your own instance of IServiceProvider.</param>
public static DotvvmConfiguration UseDotVVM<TStartup, TServiceConfigurator>(this IAppBuilder app, string applicationRootPath, bool useErrorPages = true, bool debug = true, Func<IServiceCollection, IServiceProvider> serviceProviderFactoryMethod = null)
where TStartup : IDotvvmStartup, new()
where TServiceConfigurator : IDotvvmServiceConfigurator, new()
{
return app.UseDotVVM(applicationRootPath, useErrorPages, debug, new TServiceConfigurator(), new TStartup());
return app.UseDotVVM(applicationRootPath, useErrorPages, debug, new TServiceConfigurator(), new TStartup(), serviceProviderFactoryMethod);
}

/// <summary>
Expand All @@ -43,14 +44,15 @@ public static DotvvmConfiguration UseDotVVM<TStartup, TServiceConfigurator>(this
/// in production.
/// </param>
/// <param name="debug">A value indicating whether the application should run in debug mode.</param>
public static DotvvmConfiguration UseDotVVM<TStartup>(this IAppBuilder app, string applicationRootPath, bool useErrorPages = true, bool debug = true)
/// <param name="serviceProviderFactoryMethod">Register factory method to create your own instance of IServiceProvider.</param>
public static DotvvmConfiguration UseDotVVM<TStartup>(this IAppBuilder app, string applicationRootPath, bool useErrorPages = true, bool debug = true, Func<IServiceCollection, IServiceProvider> serviceProviderFactoryMethod = null)
where TStartup : IDotvvmStartup, new()
{
var startup = new TStartup();
return app.UseDotVVM(applicationRootPath, useErrorPages, debug, startup as IDotvvmServiceConfigurator, startup);
return app.UseDotVVM(applicationRootPath, useErrorPages, debug, startup as IDotvvmServiceConfigurator, startup, serviceProviderFactoryMethod);
}

private static DotvvmConfiguration UseDotVVM(this IAppBuilder app, string applicationRootPath, bool useErrorPages, bool debug, IDotvvmServiceConfigurator configurator, IDotvvmStartup startup)
private static DotvvmConfiguration UseDotVVM(this IAppBuilder app, string applicationRootPath, bool useErrorPages, bool debug, IDotvvmServiceConfigurator configurator, IDotvvmStartup startup, Func<IServiceCollection, IServiceProvider> serviceProviderFactoryMethod = null)
{
var config = DotvvmConfiguration.CreateDefault(s => {
s.TryAddSingleton<IDataProtectionProvider>(p => new DefaultDataProtectionProvider(app));
Expand All @@ -61,7 +63,7 @@ private static DotvvmConfiguration UseDotVVM(this IAppBuilder app, string applic
s.TryAddScoped<DotvvmRequestContextStorage>(_ => new DotvvmRequestContextStorage());
s.TryAddScoped<IDotvvmRequestContext>(services => services.GetRequiredService<DotvvmRequestContextStorage>().Context);
configurator?.ConfigureServices(new DotvvmServiceCollection(s));
});
}, serviceProviderFactoryMethod);
config.Debug = debug;
config.ApplicationPhysicalPath = applicationRootPath;

Expand Down
5 changes: 3 additions & 2 deletions src/DotVVM.Framework/Configuration/DotvvmConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -164,13 +164,14 @@ internal DotvvmConfiguration()
/// Creates the default configuration and optionally registers additional application services.
/// </summary>
/// <param name="registerServices">An action to register additional services.</param>
public static DotvvmConfiguration CreateDefault(Action<IServiceCollection> registerServices = null)
/// <param name="serviceProviderFactoryMethod">Register factory method to create your own instance of IServiceProvider.</param>
public static DotvvmConfiguration CreateDefault(Action<IServiceCollection> registerServices = null, Func<IServiceCollection, IServiceProvider> serviceProviderFactoryMethod = null)
{
var services = new ServiceCollection();
DotvvmServiceCollectionExtensions.RegisterDotVVMServices(services);
registerServices?.Invoke(services);

return new ServiceLocator(services).GetService<DotvvmConfiguration>();
return new ServiceLocator(services, serviceProviderFactoryMethod).GetService<DotvvmConfiguration>();
}

/// <summary>
Expand Down
7 changes: 4 additions & 3 deletions src/DotVVM.Framework/Configuration/ServiceLocator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ namespace DotVVM.Framework.Configuration
{
public class ServiceLocator
{
private Func<IServiceCollection, IServiceProvider> serviceProviderFactoryMethod;
private IServiceCollection serviceCollection;
private IServiceProvider serviceProvider;

Expand All @@ -16,22 +17,22 @@ public ServiceLocator(IServiceProvider serviceProvider)
this.serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
}

public ServiceLocator(IServiceCollection serviceCollection)
public ServiceLocator(IServiceCollection serviceCollection, Func<IServiceCollection, IServiceProvider> serviceProviderFactoryMethod = null)
{
this.serviceProviderFactoryMethod = serviceProviderFactoryMethod;
this.serviceCollection = serviceCollection ?? throw new ArgumentNullException(nameof(serviceCollection));
}

public IServiceProvider GetServiceProvider()
{
if (serviceProvider == null)
{
serviceProvider = BuildServiceProvider();
serviceProvider = (serviceProviderFactoryMethod ?? BuildServiceProvider).Invoke(serviceCollection);
serviceCollection = null;
}
return serviceProvider;
}

[MethodImpl(MethodImplOptions.NoInlining)]
private IServiceProvider BuildServiceProvider()
{
return BuildServiceProvider(serviceCollection);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ namespace DotVVM.Framework.Runtime
[Obsolete(DefaultStaticCommandServiceLoader.DeprecationNotice)]
public class DefaultStaticCommandServiceLoader : IStaticCommandServiceLoader
{
public const string DeprecationNotice = "IStaticCommandServiceLoader is only temporary workaround for a flaw in service registration in DotVVM.Hosting.OWIN and it will be removed soon. If you need to use it, you are doing something wrong.\n\nSee discussion at https://github.com/riganti/dotvvm/commit/46f043d28f5bda2f83f2bf827c65a2c32d56e252 and https://github.com/riganti/dotvvm/commit/3036726a9783bb953ddf1b7b9a62f2c27d0db7b3 for some context.";
public const string DeprecationNotice = "IStaticCommandServiceLoader is an only temporary workaround for a flaw in service registration in DotVVM.Hosting.OWIN and it will be REMOVED SOON!. " +
"\n\rNow you can replace IServiceProvider by your own in Startup class by using optional parameter 'Func<IServiceConllection, IServiceProvider> serviceProviderFactoryMethod' in app.UseDotVVM() method.";
public virtual object GetStaticCommandService(Type serviceType, IDotvvmRequestContext context)
{
return context.Services.GetRequiredService(serviceType);
Expand Down

0 comments on commit 6b0fb38

Please sign in to comment.