ASP.Net Web 表单中的 Autofac 日志记录模块和解析参数
Autofac logging module & Resolved Parameter in ASP.Net Web Forms
我正在尝试使用 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 });
};
}
}
NLoggerclass:
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 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)
据我了解,在 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
。
我正在尝试使用 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 });
};
}
}
NLoggerclass:
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 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)
据我了解,在 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
。