Rahul Rahul -4 years ago 249
C# Question

Autofac - Resolve dependencies in WebApi controllers of seperate assemblies

I have two projects in a visual studio solution

ProjectA - Owin Selfhost Webapi application

ProjectB - A Class Library Application (References ProjectA) WebApi controllers are added here

The ProjectB controllers are resolved in ProjectA by Overriding DefaultAssembliesResolver as explained here.

ProjectA Code:

//WebApi startup class
public class Startup
{
public void Configuration(IAppBuilder app)
{

var config = new HttpConfiguration();
config.Services.Replace(typeof(IAssembliesResolver), new MyAssemblyResolver());

var builder = new ContainerBuilder();

var assemblies = GetExternalControllerAssemblier();
assemblies.Add(Assembly.GetExecutingAssembly());

builder.RegisterApiControllers(assemblies.ToArray());

//Builder reference is passed to external controllers and builder object is updated there
HandleExtControllerDependency(ref builder, assemblies);

var container = builder.Build();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
app.UseAutofacMiddleware(container);
app.UseAutofacWebApi(config);
}
}

//I'm using reflection and calling a method in external assembly, to update `builder` object.
private void HandleExtControllerDependency(ref builder, List<Assembly> assemblies)
{
foreach (component in assemblies)
{
var type = assembly.GetType(component+"DependencyHandler");
IDependencyHandler handler = Activator.CreateInstance(type) as IDependencyHandler;
handler.LoadDependencies(ref builder);
}
}


Project B Code:
The
builder
object passed from ProjectA will be updated here.

public class DependencyHandler : IDependencyHandler
{
public void LoadDependencies(ref ContainerBuilder builder)
{
builder.RegisterType<Demo>().As<IDemo>();
}
}


ISSUE:

I have a controller called DemoController and there is a parameterless constructor. I'm expecting AutoFac to inject the dependency. Seems dependency is not resolved in a controller. Im getting following error:


An error occurred when trying to create a controller of type
'DemoController'. Make sure that the controller has a parameterless
public constructor.


Question

1) Is my approach to resolve the dependency in external assembly is correct? Is there any better alternative?

2) Should i need this code?
builder.RegisterApiControllers(assemblies.ToArray());


3) How can I solve this issue?

Answer Source

Autofac provides a simple mechanism to achieve my requirement. I have resolved this by using AutoFac Assembly Scanning.

1) Create a class and extend with Module class and override the Load method. In the Overridden method register the dependency.

public class AModule : Module
{
  protected override void Load(ContainerBuilder builder)
  {
    builder.Register(c => new AComponent()).As<AComponent>();
  }
}

public class BModule : Module
{
  protected override void Load(ContainerBuilder builder)
  {
    builder.Register(c => new BComponent()).As<BComponent>();
  }
}

2) Register the Modules in Main Application:

var assembly = typeof(AComponent).Assembly;
var builder = new ContainerBuilder();

// Registers both modules
builder.RegisterAssemblyModules(assembly);

Note: Don't forget to register external controllers by calling

builder.RegisterApiControllers(<assembly array>);

That's it. Happy Coding!

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download