RuSh
RuSh

Reputation: 1693

Autofac logging module & Resolved Parameter in ASP.Net Web Forms

I'm trying to use an Autofac module to inject NLog logger to asp.net Web Forms application (code behind) but i'm getting an error when trying to use a ResolvedParameter:

Global asax & Logging module:

public class Global : HttpApplication, IContainerProviderAccessor
{

    static IContainerProvider _containerProvider;
    public IContainerProvider ContainerProvider
    {
        get { return _containerProvider; }
    }

    void Application_Start(object sender, EventArgs e)
    {
        var builder = new ContainerBuilder();
        builder.RegisterModule<LoggingModule>();
        _containerProvider = new ContainerProvider(builder.Build());

    }
}

 public class LoggingModule : Module
 {
     protected override void Load(ContainerBuilder builder)
     {
         builder.Register(RegsiterFunc).AsImplementedInterfaces();
     }

     private NLogger RegsiterFunc(IComponentContext arg, IEnumerable<Parameter> parameters)
     {
         return new NLogger(parameters.TypedAs<Type>());
     }

    protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration)
    {
        registration.Preparing +=
            (sender, args) =>
            {
                var forType = args.Component.Activator.LimitType;

                var logParameter = new ResolvedParameter(
                    (p, c) => p.ParameterType == typeof(ILogger),
                    (p, c) => c.Resolve<ILogger>(TypedParameter.From(forType)));

                 args.Parameters = args.Parameters.Union(new[] { logParameter });
            };
    }


}

NLogger class:

public class NLogger : ILogger
    {
        private readonly Logger m_Logger;

        public NLogger(Type type)
        {
            m_Logger = LogManager.GetLogger(type.FullName);
        }

        public NLogger(string typeName)
        {
            m_Logger = LogManager.GetLogger(typeName);
        }

    .......
}

Aspx page code behind:

public partial class _Default : Page
{
    public ILogger m_Logger { get; set; }
    protected void Page_Load(object sender, EventArgs e)
    {
        m_Logger.Error("test");
    }
}

To initiate the log based on the requesting type I'm using a ResolvedParameter.

The line parameters.TypedAs() in RegsiterFunc throws an exception: "Sequence contains no elements".

Same code works in asp.net MVC application but fails in the web forms project.

System.InvalidOperationException occurred HResult=0x80131509 Message=Sequence contains no elements Source=Autofac StackTrace: at Autofac.ParameterExtensions.ConstantValue[TParameter,TValue](IEnumerable`1 parameters, Func`2 predicate) at Autofac.ParameterExtensions.TypedAs[T](IEnumerable`1 parameters) at WebApplication1.LoggingModule.RegsiterFunc(IComponentContext arg, IEnumerable`1 parameters) in Global.asax.cs:line 55 at Autofac.Builder.RegistrationBuilder.<>c__DisplayClass0_0`1.b__0(IComponentContext c, IEnumerable`1 p) at Autofac.Core.Activators.Delegate.DelegateActivator.ActivateInstance(IComponentContext context, IEnumerable`1 parameters) at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1 parameters)

Upvotes: 2

Views: 654

Answers (1)

felix-b
felix-b

Reputation: 8498

As far as I understand, in RegsiterFunc you are attempting to retrieve type of component the logger is being injected into.

But the parameter that carries component type is not a TypedParameter, but rather it's a NamedParameter. That's why you get the exception.

Though less elegant, but working version of RegsiterFunc:

private NLogger RegsiterFunc(IComponentContext arg, IEnumerable<Parameter> parameters)
{
    var type = (Type)((NamedParameter)parameters.First()).Value;
    return new NLogger(type);
}

Then for Default.aspx page, the type passed to NLogger will be ASP.default_aspx.

The second parameter you create:

new ResolvedParameter(
    (p, c) => p.ParameterType == typeof(ILogger),
    (p, c) => c.Resolve<ILogger>(TypedParameter.From(forType)));

is not in use, so that overriding AttachToComponentRegistration is unnecessary.

Upvotes: 3

Related Questions