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