【问题标题】:Autofac logging module & Resolved Parameter in ASP.Net Web FormsASP.Net Web 表单中的 Autofac 日志记录模块和解析参数
【发布时间】:2017-07-16 14:42:13
【问题描述】:

我正在尝试使用 Autofac 模块将 NLog 记录器注入 asp.net Web Forms 应用程序(代码隐藏),但在尝试使用 ResolvedParameter 时出现错误:

全局 asax 和日志记录模块:

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 类:

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页面代码:

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

要根据请求类型启动日志,我使用的是 ResolvedParameter。

RegsiterFunc 中的 parameters.TypedAs() 行抛出异常:“Sequence contains no elements”。

相同的代码在 asp.net MVC 应用程序中工作,但在 Web 表单项目中失败。

System.InvalidOperationException 发生 HResult=0x80131509 Message=Sequence 不包含任何元素 Source=Autofac StackTrace:在 Autofac.ParameterExtensions.ConstantValue[TParameter,TValue](IEnumerable`1 参数,Func`2 谓词) 在 Autofac.ParameterExtensions.TypedAs[T](IEnumerable`1 参数) 在 Global.asax.cs:line 55 中的 WebApplication1.LoggingModule.RegsiterFunc(IComponentContext arg, IEnumerable`1 参数) 在 Autofac.Builder.RegistrationBuilder.c__DisplayClass0_0`1.b__0(IComponentContext c, IEnumerable`1 p) 在 Autofac.Core.Activators.Delegate.DelegateActivator.ActivateInstance(IComponentContext 上下文,IEnumerable`1 参数) 在 Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1 参数)

【问题讨论】:

    标签: c# asp.net webforms autofac nlog


    【解决方案1】:

    据我了解,在RegsiterFunc 中,您正试图检索记录器被注入的组件类型。

    但是携带组件类型的参数不是TypedParameter,而是NamedParameter。这就是你得到异常的原因。

    虽然不那么优雅,但RegsiterFunc 的工作版本:

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

    那么对于 Default.aspx 页面,传递给 NLogger 的类型将是 ASP.default_aspx

    你创建的第二个参数:

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

    未使用,因此无需覆盖AttachToComponentRegistration

    【讨论】:

    • 很好的解决方案,您的代码正在运行。我认为“注入”(源)组件的类型仅在 AttachToComponentRegistration 阶段可用。此外,您正在使用 NamedParameter 但在使用它之前未设置此参数。源组件的类型是否总是自动作为第一个命名参数可用?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-13
    • 1970-01-01
    • 1970-01-01
    • 2017-06-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多