Explicit resolving of ILog in Autofac when using with Log Injection Module

前端 未结 3 2236
一向
一向 2021-01-01 04:15

I use the following code in order to register log4net for all the classes that need it.

public class LogInjectionModule : Module
{
    private readonly strin         


        
相关标签:
3条回答
  • 2021-01-01 04:29

    Your LogInjectionModule never registers any ILog 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 the ClassThatNeedsILog manually. with new ClassThatNeedsILog(...)

    Hence Autofac does not know about your instance creation (so your OnComponentPreparing won't run) and because you haven't really registered any ILog implementation you get the ComponentNotRegisteredException.

    You have two options:

    • register an ILog in the container directly
    • let Autofac create your ClassThatNeedsILog type.

    So you can just register an ILog in the container with:

    builder.RegisterInstance(LogManager.GetLogger("Logger")).As<ILog>();
    

    Then your code will work fine.

    Or if you anyway creating the ClassThatNeedsILog by hand can just supply directly the ILog there:

     builder.Register(x => new 
         ClassThatNeedsILog(LogManager.GetLogger(typeof(ClassThatNeedsILog))))
         .AsImplemen‌​tedInterfaces();
    

    The other options is to let Autofac create the instances for you, so change your registration to:

     builder.RegisterType<ClassThatNeedsILog>()
         .AsImplemen‌​tedInterfaces();
    

    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 and WithParameters methods:

     builder.RegisterType<ClassThatNeedsILog>()
         .AsImplemen‌​tedInterfaces()
         .WithParameters(new Parameter[] {
             ResolvedParameter.ForNamed<IAnotherInterface>("NAME"),
             ResolvedParameter.ForNamed<IYetAnotherInterface>("ANOTHERNAME")});
    
    0 讨论(0)
  • 2021-01-01 04:35

    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:

    config.Filters.AddRange(config.DependencyResolver.GetServices(typeof(IExceptionFilter)).Select(o => o as IExceptionFilter));
    

    Just adding mentioning it here, if other's have forgotten to configure the filter in the first place.

    0 讨论(0)
  • 2021-01-01 04:45

    The builder needs to Build a container before it can Resolve.

    Try something like this (untested)

    builder
        .RegisterAssemblyTypes(typeof (IResourceFinder).Assembly)
        .AsImplementedInterfaces();
    /* process LogInjectionModule */
    IContainer container = builder.Build();
    
    var updateBuilder = new ContainerBuilder();
    updateBuilder
        .Register(x => new ClassThatNeedsILog(x.Resolve<ILog>()))
        .AsImplementedInterfaces();
    updateBuilder.Update(container);
    
    0 讨论(0)
提交回复
热议问题