I use the following code in order to register log4net for all the classes that need it.
public class LogInjectionModule : Module
{
private readonly string _configPath;
public LogInjectionModule(string configPath)
{
_configPath = configPath;
}
protected override void AttachToComponentRegistration(IComponentRegistry registry,
IComponentRegistration registration)
{
XmlConfigurator.Configure(new FileInfo(_configPath));
registration.Preparing += OnComponentPreparing;
}
private static void OnComponentPreparing(object sender, PreparingEventArgs e)
{
var t = e.Component.Activator.LimitType;
e.Parameters = e.Parameters.Union(new[]
{
new ResolvedParameter((p, i) => p.ParameterType == typeof (ILog),
(p, i) => LogManager.GetLogger(t))
});
}
}
All the classes are registered using autofac's types scanning:
builder.RegisterAssemblyTypes(typeof (IResourceFinder).Assembly)
.AsImplementedInterfaces();
And it works fine!
One class needs to be registered explicitly tries to resolve ILog and fails
builder.Register(x => new ClassThatNeedsILog(x.Resolve<ILog>())).AsImplementedInterfaces();
Here is that class
public class ClassThatNeedsILog
{
public ClassThatNeedsILog(ILog log)
{
}
}
I am getting the following exception:
Autofac.Core.Registration.ComponentNotRegisteredException : The requested service 'log4net.ILog' has not been registered. To avoid this exception, either register a component to provide the service, check for service registration using IsRegistered(), or use the ResolveOptional() method to resolve an optional dependency.
Your
LogInjectionModule
never registers anyILog
into the container only supplies paramters for the resolved instances on the preparing face, and it only works for instances created by Autofac.So when you write
builder.Register(x => new ClassThatNeedsILog(x.Resolve<ILog>()))
you are creating theClassThatNeedsILog
manually. withnew ClassThatNeedsILog(...)
Hence Autofac does not know about your instance creation (so your
OnComponentPreparing
won't run) and because you haven't really registered anyILog
implementation you get theComponentNotRegisteredException
.You have two options:
ILog
in the container directlyClassThatNeedsILog
type.So you can just register an
ILog
in the container with:Then your code will work fine.
Or if you anyway creating the
ClassThatNeedsILog
by hand can just supply directly theILog
there:The other options is to let Autofac create the instances for you, so change your registration to:
In this case Autofac will handle the instance creation for you and it will call the
OnComponentPreparing
method of your module.If you want to supply additional constructor parameters you can use
WithParameter
andWithParameters
methods:The
builder
needs toBuild
acontainer
before it canResolve
.Try something like this (untested)
nemesv's answer resolved the issue for me.
Though, I had to spend some more time getting it to work after using the RegisterType approach, as I was missing the below:
Just adding mentioning it here, if other's have forgotten to configure the filter in the first place.