Blacklite / DependencyInjection

Dependency injection addins for AspNet 5
2 stars 1 forks source link

Auto-wire services? #2

Open Antaris opened 9 years ago

Antaris commented 9 years ago

Hi,

Just discovered this whilst looking more at ICompileModule, seems you're ahead of me on an idea I've been pondering about auto-wiring services (ala MEF) for ASP.NET 5.

Generally, my idea is along the lines of:

[Transient]
public class Service : IService { }

And have an ICompileModule generate a class through precompilation, such like:

public static class AutoWireServicesExtensions
{
    public static void AutoWire(this IServicesCollection services)
    {
        services.AddTransient<IService, Service>();
    }
}

Which is then added to the compilation, perhaps then modifying the Startup class:

ConfigureServices(IServiceCollection services) 
{
    services.AutoWire();
}

I get the feeling you're actually further along with I am with this train of thought, so its interesting to know where you are at so far?

I think this sort of model could probably be extended to automatically wireup the pipeline middleware too,

[Middleware("MyMiddleware")]
public class MyMiddleware: IMiddleware
{
    public void RegisterMiddleware(IApplicationBuilder app)
    {
        app.UseMiddleware<...>();
    }
}

What I am looking to achieve, is pluggable modules using the ASP.NET 5 runtime model, and how we can create dynamic runtime pipelines, and automatic dependency wireup, without the developer having to do a whole load of bootstrapping work anytime they want to add a new module in.

It works ok for simple 1-project websites, but needs more consideration for more complex CMS-type projects.

What is your current thoughts on this, if you have any?

david-driscoll commented 9 years ago

It is entirely possible to modify the Startup class, in fact the way the code works is that it locates the call to AddAssembly and replaces that. The code might not work at the moment, I haven't sat down and updated it for Beta3 yet.

I went down this path at first because it seemed to make the most sense, in that it gives the library author / application author the ability to control the usage explicitly, instead of using magic. It just compiles down to something that works better at runtime than reflection.

I see two different scenarios, essentially.

  1. Registering all the types, and emitting that code. This could be as a class, adding a new class/method.
  2. Capturing all the references that expose a given class or method and then wiring them up onto the startup class.

1 should be isolated to the given assembly, it shouldn't leak unless required. There could be two, one that supports replacement of AddAssembly/FromAssembly, and then another that emits AutoWire.

2 should just can the references (Semantic Model) for any references that contain AutoWire with the correct definition.

Middleware could be similar, you would have to consider how to order them from each other as order may be very important. Blacklite/Steps uses a Topographical Sort for this, but a simple priority would work as well.

You'd have to make sure that you can integrated it fairly well with any other Middleware that the user also wants to place in, but you could use marker extension methods or something like that for that one.

Antaris commented 9 years ago

Yeah, the bit that bothers me about my current setup, is either you use reflection for your magic, or you have to type things by hand. We have a TypeFinder class, but this has to scan assemblies, maintain a list of exported types, and then providers an IQueryable api over methods like GetSubclasses<T> etc. The problem with this, is there is a fair amount of work an app has to do at startup before the first request is processed.

Now with Rosyln it gives us the chance to find a middle ground, whereby you can still control things by hand, but there is an element of magic working behind the scenes at compile time. I'd rather work with a flat list of services.Add[*] calls instead of reflection, so this approach is better.

I'll keep an eye on this repo, I think you're onto something good..