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.
I think it's a great idea, I would use the var keyword instead of any though. Just because that's currently being used for type-safe variables which the compiler figures out the type for.