lonix
lonix

Reputation: 20591

Property injection with Autofac and ASP.NET Core controller

My controller classes have a single dependency, e.g.:

public class UserController : ControllerBase {
  public UserController(IMediator mediator) => _mediator = mediator;
  private readonly IMediator _mediator;
}

But that must be duplicated in all my controllers. I'd prefer to do property injection, so I could clean it up like this:

public abstract class MyControllerBase : ControllerBase {
  public IMediator Mediator { get; init; }  // use init so container resolves this and cannot be changed later
}

public class UserController : MyControllerBase {
}

To get that working, I followed the docs.

I changed my Startup.ConfigureServices():

services.AddControllers().AddControllersAsServices();

And I registered controllers in Startup.ConfigureContainer(ContainerBuilder builder):

builder
  .RegisterAssemblyTypes(typeof(Startup).Assembly)
  .AssignableTo<MyControllerBase>()
  .InstancePerLifetimeScope()
  .PropertiesAutowired();

That works.

However the docs say that I can inject a specific property:

If you have one specific property and value to wire up, you can use the WithProperty() modifier: builder.RegisterType<A>().WithProperty("PropertyName", propertyValue);

So I have to change my code:

var types =
  typeof(Startup).Assembly
  .GetExportedTypes()
  .Where(type => typeof(MyControllerBase).IsAssignableFrom(type))
  .ToArray();

foreach (var type in types)
  builder.RegisterType(type).WithProperty(nameof(MyControllerBase.Mediator), propertyValue);

How can I dynamically resolve propertyValue from the container. AND, will the container inject any other properties in controller classes, or would it inject that one only?

Upvotes: 0

Views: 576

Answers (1)

Nkosi
Nkosi

Reputation: 247088

What you are trying to do wasn't meant for that scenario. As you have already encountered, it for if the specific value is known at the time of setup not about dynamic resolution.

I suggest leaving it the way it was working before where the container will resolve the dependency and set the property.

//...

public void ConfigureContainer(ContainerBuilder builder) { 
    var types =
        typeof(Startup).Assembly
        .GetExportedTypes()
        .Where(type => typeof(MyControllerBase).IsAssignableFrom(type))
        .ToArray();
    
    
    builder.RegisterTypes(types).PropertiesAutowired();
}

The approach you want to take is really unnecessary given your scenario.

Upvotes: 4

Related Questions