Skip to content

Instantly share code, notes, and snippets.

@khellang
Last active August 10, 2016 09:23
Show Gist options
  • Save khellang/34135cf0a3be098fb30bc9979b4737c8 to your computer and use it in GitHub Desktop.
Save khellang/34135cf0a3be098fb30bc9979b4737c8 to your computer and use it in GitHub Desktop.
The nightmares of virtual methods.
public class MyAwesomeStartup : Startup<IContainer>
{
public MyAwesomeStartup(IServiceProviderFactory factory) : base(factory)
{
}
protected override void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
}
protected override void ConfigureContainer(IContainer builder)
{
builder.Configure(config => config.For<IGreeter>().Use<Greeter>().SetLifecycleTo<ContainerLifecycle>());
}
public override void Configure(IApplicationBuilder app)
{
app.UseMvc();
}
}
public class Greeter : IGreeter
{
public string SayHelloTo(string name) => $"Hello {name ?? "World"}!";
}
public interface IGreeter
{
string SayHelloTo(string name);
}
[Route("hello")]
public class HelloController : Controller
{
public HelloController(IGreeter greeter)
{
Greeter = greeter;
}
private IGreeter Greeter { get; }
[HttpGet("{name}")]
public string Hello(string name)
{
return Greeter.SayHelloTo(name);
}
}
public class Program
{
public static void Main(string[] args) =>
new WebHostBuilder()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseStartup<MyAwesomeStartup>()
.UseIISIntegration()
.UseStructureMap()
.UseKestrel()
.Build()
.Run();
}
public interface IServiceProviderFactory
{
object GetBuilder(IServiceCollection services);
IServiceProvider BuildServiceProvider(object builder);
}
public abstract class ServiceProviderFactory<TBuilder> : IServiceProviderFactory
{
object IServiceProviderFactory.GetBuilder(IServiceCollection services)
{
return GetBuilder(services);
}
IServiceProvider IServiceProviderFactory.BuildServiceProvider(object builder)
{
return BuildServiceProvider((TBuilder)builder);
}
protected abstract TBuilder GetBuilder(IServiceCollection services);
protected abstract IServiceProvider BuildServiceProvider(TBuilder builder);
}
public abstract class Startup<TBuilder> : IStartup
{
protected Startup(IServiceProviderFactory factory)
{
Factory = factory;
}
private IServiceProviderFactory Factory { get; }
IServiceProvider IStartup.ConfigureServices(IServiceCollection services)
{
ConfigureServices(services);
var builder = Factory.GetBuilder(services);
ConfigureContainer((TBuilder)builder);
return Factory.BuildServiceProvider(builder);
}
protected virtual void ConfigureServices(IServiceCollection services)
{
}
protected virtual void ConfigureContainer(TBuilder builder)
{
}
public abstract void Configure(IApplicationBuilder app);
}
public static class StructureMapExtensions
{
public static IWebHostBuilder UseStructureMap(this IWebHostBuilder builder)
{
return builder.ConfigureServices(services => services.AddTransient<IServiceProviderFactory, StructureMapServiceProviderFactory>());
}
private class StructureMapServiceProviderFactory : ServiceProviderFactory<IContainer>
{
protected override IContainer GetBuilder(IServiceCollection services)
{
var container = new Container();
container.Populate(services);
return container;
}
protected override IServiceProvider BuildServiceProvider(IContainer container)
{
return container.GetInstance<IServiceProvider>();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment