Autofac记录模块和ASP.Net Web窗体中的已解析参数

问题描述:

我试图使用Autofac模块将NLog记录器注入到asp.net Web窗体应用程序(后面的代码)但试图尝试使用ResolvedParameter:Autofac记录模块和ASP.Net Web窗体中的已解析参数

全球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日志。

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

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

System.InvalidOperationException发生的HResult = 0x80131509 消息=序列不包含任何元素源= Autofac 堆栈跟踪:在Autofac.ParameterExtensions.ConstantValue [TParameter,TValue](IEnumerable的` 1参数,函数功能` 2谓词) 在Autofac.ParameterExtensions.TypedAs [T](IEnumerable ` 1 parameters) at GlobalApplication1.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) 在Autofac.Core.Activators.Delegate.DelegateActivator.ActivateInstance(IComponentContext上下文,IEnumerable的` 1参数) 在Autofac.Core.Resolving.InstanceLookup.Activate( IEnumerable的` 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是不必要的。

+0

伟大的解决方案,您的代码正在工作。我认为“注入”(源)组件的类型只能在AttachToComponentRegistration阶段使用。你也使用了NamedParameter,但是在使用它之前没有设置它。源组件的类型是否始终作为第一个命名参数自动可用? – RuSh