I seem to be doing this a fair bit in my code:
public class ActionsModule : Module
{
protected override void Load(ContainerBuilder builder)
{
base.Load(builder);
builder.Register(c => LogManager.GetCurrentClassLogger()).As<ILog>().InstancePerDependency();
// Autofac doesn't seem to be able to inject things without explicit binding
builder.RegisterType<ComboActions>().As<ComboActions>().InstancePerHttpRequest();
builder.RegisterType<AppActions>().As<AppActions>().InstancePerHttpRequest();
}
}
}
Where the 'actions' class is a class I require to be injected into my controller, and has various other sub-dependencies.
Seems a bit rubbish. Why can't autofac resolve that the class has a constructor with dependencies that are already satisfied and manufacture an instance automatically?
I mean, if class A requires class B to be injected and class B requires C, D, E, etc. fair enough, I guess you dont want to walk the entire dependency chain to see if you can make a class at run time. ...but if class A directly depends on C and D which are explicitly bound, surely that's a trivial case?
Am I missing something? Can't seem to see any documentation for this...
You don't have to register every type. Autofac provides a AnyConcreteTypeNotAlreadyRegisteredSource that will automatically grab a concrete type if you haven't already provided a registration.
For example:
var builder = new ContainerBuilder();
builder.RegisterSource(new AnyConcreteTypeNotAlreadyRegisteredSource());
var container = builder.Build();
...
var myConcreteType = container.Resolve<MyConcreteType>();
The sources allow more complex things, like automatically injecting mocked objects for interfaces and abstract class based dependencies.
AFAIK, Autofac requires every needed type to be registered in the container, but this does not mean you have to do each one individually. Almost 99% of my registrations are handled by adding this attribute to the type:
[AttributeUsage(AttributeTargets.Class)]
public class AutoRegisterAttribute : Attribute { }
So for example, you'd have
[AutoRegister]
class ComboActions
{
And then I register them with this:
public class AutoScanModule : Module
{
private readonly Assembly[] _assembliesToScan;
public AutoScanModule(params Assembly[] assembliesToScan)
{
_assembliesToScan = assembliesToScan;
}
protected override void Load(ContainerBuilder builder)
{
builder.RegisterAssemblyTypes(_assembliesToScan)
.Where(t => t.GetCustomAttributes(typeof (AutoRegisterAttribute), false).Any())
.AsSelf()
.AsImplementedInterfaces()
.InstancePerLifetimeScope();
}
}
Like I said, this covers most of my registrations and then I usually only have to worry about things like 3rd party types, open generics and decorators.
EDIT: Check out the reply from Kaleb that proves me wrong. Cool feature I never knew about!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With