In the new ASP.NET 5 stack dependency injection is pervasive. We let users wire up their dependencies in the Startup
class:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<IFoo, Foo>();
}
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory, IFoo foo)
{
loggerFactory.AddConsole();
app.UseMvc();
}
}
In the above snippet, the Configure method has a single required parameter, all other parameters are optional. Let's say we wanted to define an interface for this class so that we get type safety and the benefits of refactoring:
public interface IStartup
{
void ConfigureServices(IServiceCollection services);
void Configure(IApplicationBuilder app, object params[] args);
}
The problem with this is that the implemenation of the interface can't get ILoggerFactory
and IFoo
without casting from object.
Enter type safe params:
public interface IStartup
{
void ConfigureServices(IServiceCollection services);
void Configure(IApplicationBuilder app, any params[] args);
}
public class Startup : IStartup
{
public void ConfigureServices(IServiceCollection services)
{
}
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory, IFoo environment)
{
loggerFactory.AddConsole();
app.UseMvc();
}
}
The compiler would generate:
public class Startup : IStartup
{
public void ConfigureServices(IServiceCollection services)
{
}
[CompilerGenerated]
void IStartup.Configure(IApplicationBuilder app, params object[] args)
{
Configure(app, (ILoggerFactory)args[0], (IFoo)args[1]);
}
// User defined method
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory, IFoo environment)
{
loggerFactory.AddConsole();
app.UseMvc();
}
}
This only helps the user implementing the interface, the caller is likely still using reflection to call the user method.
But placing such power in the wrong hands... imagine the kind of mess people would get into with such a construct.
I love that the new OWIN practices don't force the user into writing any service location, and totally understand why an interface wasn't possible. Is it really that confusing for people to work by convention as opposed to an interface? If it is, should we be empowering them with tools like your
any
keyword?