Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Autofac registering everything that ends with Service

So Im using autofac in a MVC so my controllers can have there dependencies injected on there constructor, I have in my Global.asax I have the following snippet of code, which works.

// Register your MVC controllers.
builder.RegisterControllers(typeof(MvcApplication).Assembly);

builder.RegisterType<PurchaseOrderSearchService>().As<IPurchaseOrderSearchService>().WithParameter("context", new PurchaseOrderManagerContext());

// Set the dependency resolver to be Autofac.
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

The problem is I don't want to do builder.RegisterType over and over again, for all my Services. So how do I do that?

I think the kind of thing I want is

builder.RegisterAssemblyTypes(foo)
   .Where(t => t.Name.EndsWith("Services"))
   .WithParameter("context", new PurchaseOrderManagerContext());

But no idea what foo should be. Or if RegisterAssemblyTypes is correct way. I know coding by convention is the solution but not sure what the convention is. All my services will end int word Service and will have interface

so FooService will have interface IFooService and BarService will have interface IBarService

Should also point out that all the services live in a class library called PurchaseOrderManager.Service

like image 509
Ashley Kilgour Avatar asked May 20 '16 12:05

Ashley Kilgour


People also ask

How do I register an Autofac service?

Register by Type var builder = new ContainerBuilder(); builder. RegisterType<ConsoleLogger>(); builder. RegisterType(typeof(ConfigReader)); When using reflection-based components, Autofac automatically uses the constructor for your class with the most parameters that are able to be obtained from the container.

Why should I use Autofac?

AutoFac provides better integration for the ASP.NET MVC framework and is developed using Google code. AutoFac manages the dependencies of classes so that the application may be easy to change when it is scaled up in size and complexity.

How do I get Autofac containers?

From Visual Studio, you can get it via NuGet. The package name is Autofac. Alternatively, the NuGet package can be downloaded from the GitHub repository (https://github.com/autofac/Autofac/releases).

What is Autofac in C#?

Autofac is an addictive Inversion of Control container for . NET Core, ASP.NET Core, . NET 4.5. 1+, Universal Windows apps, and more.


1 Answers

You're on the right track. "Foo" should be the assembly containing the types to register - if you're using a single assembly then the following should work:

builder.RegisterAssemblyTypes(typeof(MvcApplication).Assembly)
    .Where(t => t.Name.EndsWith("Services"))
    .WithParameter("context", new PurchaseOrderManagerContext())
    .AsImplementedInterfaces();

The .AsImplementedInterfaces() is needed to register them as IFooService - without it, they would only be registered as FooService etc.

If your classes live in a separate assembly, I would normally recommend you define an autofac module within that assembly:

public class ServiceModule : Module 
{
    protected override void Load(ContainerBuilder builder)
    {
        // "ThisAssembly" means "any types in the same assembly as the module"
        builder.RegisterAssemblyTypes(ThisAssembly)
            .Where(....
    }
}

Then register this in your web application:

builder.RegisterModule<PurchaseOrderManager.Service.ServiceModule>();

Alternatively, use my original suggestion but explicitly specify the assembly containing the services:

builder.RegisterAssemblyTypes(typeof(PurchaseOrderManager.Service.FooService).Assembly)
    .Where(t => t.Name.EndsWith("Services"))
    .WithParameter("context", new PurchaseOrderManagerContext())
    .AsImplementedInterfaces();

You just need to pick any class which exists in that assembly.

like image 137
Richard Avatar answered Nov 11 '22 00:11

Richard