Asp.net web api 使用Autofac将NLog注入Web Api控制器
我正在尝试使用Autofac将NLog添加到我的Web Api项目中。但我有问题 从NuGet安装NLog包后,我将以下文件添加到我的项目中。 (由于以下不同的帖子和例子可能会混淆) ILogger.csAsp.net web api 使用Autofac将NLog注入Web Api控制器,asp.net-web-api,autofac,nlog,Asp.net Web Api,Autofac,Nlog,我正在尝试使用Autofac将NLog添加到我的Web Api项目中。但我有问题 从NuGet安装NLog包后,我将以下文件添加到我的项目中。 (由于以下不同的帖子和例子可能会混淆) ILogger.cs public interface ILogger { void Debug(string message); void Trace(string message); void Info(string message); void
public interface ILogger {
void Debug(string message);
void Trace(string message);
void Info(string message);
void Warning(string message);
void Error(string message);
void Error(string message, Exception exception);
void Fatal(string message);
void Fatal(string message, Exception exception);
}
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Class)]
public class LoggerAttribute : Attribute {
public readonly string Name;
public LoggerAttribute(string name) {
Name = name;
}
}
public class NLogger : ILogger {
private readonly NLog.Logger logger;
public NLogger(Type loggerType) {
logger = LogManager.GetLogger(loggerType.FullName);
}
public void Debug(string message) {
logger.Debug(message);
}
public void Trace(string message) {
logger.Trace(message);
}
public void Info(string message) {
logger.Info(message);
}
public void Warning(string message) {
logger.Warn(message);
}
public void Error(string message) {
logger.Error(message);
}
public void Error(string message, Exception exception) {
logger.ErrorException(message, exception);
}
public void Fatal(string message) {
logger.Fatal(message);
}
public void Fatal(string message, Exception exception) {
logger.FatalException(message, exception);
}
}
public class NLogModule : Module {
protected override void AttachToComponentRegistration(IComponentRegistry registry, IComponentRegistration registration) {
registration.Preparing += OnComponentPreparing;
}
static void OnComponentPreparing(object sender, PreparingEventArgs e) {
var typePreparing = e.Component.Activator.LimitType;
// By default, the name supplied to the logging instance is the name of the type in which it is being injected into.
string loggerName = typePreparing.FullName;
//If there is a class-level logger attribute, then promote its supplied name value instead as the logger name to use.
var loggerAttribute = (LoggerAttribute)typePreparing.GetCustomAttributes(typeof(LoggerAttribute), true).FirstOrDefault();
if(loggerAttribute != null) {
loggerName = loggerAttribute.Name;
}
e.Parameters = e.Parameters.Union(new Parameter[]
{
new ResolvedParameter(
(p, i) => p.ParameterType == typeof (ILogger),
(p, i) =>
{
// If the parameter being injected has its own logger attribute, then promote its name value instead as the logger name to use.
loggerAttribute = (LoggerAttribute)
p.GetCustomAttributes(typeof(LoggerAttribute),true).FirstOrDefault();
if (loggerAttribute != null)
{
loggerName = loggerAttribute.Name;
}
// Return a new Logger instance for injection, parameterised with the most appropriate name which we have determined above.
return LogManager.GetLogger(loggerName);
}),
// Always make an unamed instance of Logger available for use in delegate-based registration e.g.: Register((c,p) => new Foo(p.TypedAs<Logger>())
new TypedParameter(typeof(ILogger), LogManager.GetLogger(loggerName))
});
}
}
public class TestController : ApiController
{
private IUnitOfWork uow;
private ILogger _logger;
// GET api/test
public TestController(IUnitOfWork unitOfWork, ILogger logger) {
uow = unitOfWork;
_logger = logger;
}
...
}
LoggerAttribute.cs
public interface ILogger {
void Debug(string message);
void Trace(string message);
void Info(string message);
void Warning(string message);
void Error(string message);
void Error(string message, Exception exception);
void Fatal(string message);
void Fatal(string message, Exception exception);
}
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Class)]
public class LoggerAttribute : Attribute {
public readonly string Name;
public LoggerAttribute(string name) {
Name = name;
}
}
public class NLogger : ILogger {
private readonly NLog.Logger logger;
public NLogger(Type loggerType) {
logger = LogManager.GetLogger(loggerType.FullName);
}
public void Debug(string message) {
logger.Debug(message);
}
public void Trace(string message) {
logger.Trace(message);
}
public void Info(string message) {
logger.Info(message);
}
public void Warning(string message) {
logger.Warn(message);
}
public void Error(string message) {
logger.Error(message);
}
public void Error(string message, Exception exception) {
logger.ErrorException(message, exception);
}
public void Fatal(string message) {
logger.Fatal(message);
}
public void Fatal(string message, Exception exception) {
logger.FatalException(message, exception);
}
}
public class NLogModule : Module {
protected override void AttachToComponentRegistration(IComponentRegistry registry, IComponentRegistration registration) {
registration.Preparing += OnComponentPreparing;
}
static void OnComponentPreparing(object sender, PreparingEventArgs e) {
var typePreparing = e.Component.Activator.LimitType;
// By default, the name supplied to the logging instance is the name of the type in which it is being injected into.
string loggerName = typePreparing.FullName;
//If there is a class-level logger attribute, then promote its supplied name value instead as the logger name to use.
var loggerAttribute = (LoggerAttribute)typePreparing.GetCustomAttributes(typeof(LoggerAttribute), true).FirstOrDefault();
if(loggerAttribute != null) {
loggerName = loggerAttribute.Name;
}
e.Parameters = e.Parameters.Union(new Parameter[]
{
new ResolvedParameter(
(p, i) => p.ParameterType == typeof (ILogger),
(p, i) =>
{
// If the parameter being injected has its own logger attribute, then promote its name value instead as the logger name to use.
loggerAttribute = (LoggerAttribute)
p.GetCustomAttributes(typeof(LoggerAttribute),true).FirstOrDefault();
if (loggerAttribute != null)
{
loggerName = loggerAttribute.Name;
}
// Return a new Logger instance for injection, parameterised with the most appropriate name which we have determined above.
return LogManager.GetLogger(loggerName);
}),
// Always make an unamed instance of Logger available for use in delegate-based registration e.g.: Register((c,p) => new Foo(p.TypedAs<Logger>())
new TypedParameter(typeof(ILogger), LogManager.GetLogger(loggerName))
});
}
}
public class TestController : ApiController
{
private IUnitOfWork uow;
private ILogger _logger;
// GET api/test
public TestController(IUnitOfWork unitOfWork, ILogger logger) {
uow = unitOfWork;
_logger = logger;
}
...
}
NLogger.cs
public interface ILogger {
void Debug(string message);
void Trace(string message);
void Info(string message);
void Warning(string message);
void Error(string message);
void Error(string message, Exception exception);
void Fatal(string message);
void Fatal(string message, Exception exception);
}
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Class)]
public class LoggerAttribute : Attribute {
public readonly string Name;
public LoggerAttribute(string name) {
Name = name;
}
}
public class NLogger : ILogger {
private readonly NLog.Logger logger;
public NLogger(Type loggerType) {
logger = LogManager.GetLogger(loggerType.FullName);
}
public void Debug(string message) {
logger.Debug(message);
}
public void Trace(string message) {
logger.Trace(message);
}
public void Info(string message) {
logger.Info(message);
}
public void Warning(string message) {
logger.Warn(message);
}
public void Error(string message) {
logger.Error(message);
}
public void Error(string message, Exception exception) {
logger.ErrorException(message, exception);
}
public void Fatal(string message) {
logger.Fatal(message);
}
public void Fatal(string message, Exception exception) {
logger.FatalException(message, exception);
}
}
public class NLogModule : Module {
protected override void AttachToComponentRegistration(IComponentRegistry registry, IComponentRegistration registration) {
registration.Preparing += OnComponentPreparing;
}
static void OnComponentPreparing(object sender, PreparingEventArgs e) {
var typePreparing = e.Component.Activator.LimitType;
// By default, the name supplied to the logging instance is the name of the type in which it is being injected into.
string loggerName = typePreparing.FullName;
//If there is a class-level logger attribute, then promote its supplied name value instead as the logger name to use.
var loggerAttribute = (LoggerAttribute)typePreparing.GetCustomAttributes(typeof(LoggerAttribute), true).FirstOrDefault();
if(loggerAttribute != null) {
loggerName = loggerAttribute.Name;
}
e.Parameters = e.Parameters.Union(new Parameter[]
{
new ResolvedParameter(
(p, i) => p.ParameterType == typeof (ILogger),
(p, i) =>
{
// If the parameter being injected has its own logger attribute, then promote its name value instead as the logger name to use.
loggerAttribute = (LoggerAttribute)
p.GetCustomAttributes(typeof(LoggerAttribute),true).FirstOrDefault();
if (loggerAttribute != null)
{
loggerName = loggerAttribute.Name;
}
// Return a new Logger instance for injection, parameterised with the most appropriate name which we have determined above.
return LogManager.GetLogger(loggerName);
}),
// Always make an unamed instance of Logger available for use in delegate-based registration e.g.: Register((c,p) => new Foo(p.TypedAs<Logger>())
new TypedParameter(typeof(ILogger), LogManager.GetLogger(loggerName))
});
}
}
public class TestController : ApiController
{
private IUnitOfWork uow;
private ILogger _logger;
// GET api/test
public TestController(IUnitOfWork unitOfWork, ILogger logger) {
uow = unitOfWork;
_logger = logger;
}
...
}
NLogModule.cs
public interface ILogger {
void Debug(string message);
void Trace(string message);
void Info(string message);
void Warning(string message);
void Error(string message);
void Error(string message, Exception exception);
void Fatal(string message);
void Fatal(string message, Exception exception);
}
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Class)]
public class LoggerAttribute : Attribute {
public readonly string Name;
public LoggerAttribute(string name) {
Name = name;
}
}
public class NLogger : ILogger {
private readonly NLog.Logger logger;
public NLogger(Type loggerType) {
logger = LogManager.GetLogger(loggerType.FullName);
}
public void Debug(string message) {
logger.Debug(message);
}
public void Trace(string message) {
logger.Trace(message);
}
public void Info(string message) {
logger.Info(message);
}
public void Warning(string message) {
logger.Warn(message);
}
public void Error(string message) {
logger.Error(message);
}
public void Error(string message, Exception exception) {
logger.ErrorException(message, exception);
}
public void Fatal(string message) {
logger.Fatal(message);
}
public void Fatal(string message, Exception exception) {
logger.FatalException(message, exception);
}
}
public class NLogModule : Module {
protected override void AttachToComponentRegistration(IComponentRegistry registry, IComponentRegistration registration) {
registration.Preparing += OnComponentPreparing;
}
static void OnComponentPreparing(object sender, PreparingEventArgs e) {
var typePreparing = e.Component.Activator.LimitType;
// By default, the name supplied to the logging instance is the name of the type in which it is being injected into.
string loggerName = typePreparing.FullName;
//If there is a class-level logger attribute, then promote its supplied name value instead as the logger name to use.
var loggerAttribute = (LoggerAttribute)typePreparing.GetCustomAttributes(typeof(LoggerAttribute), true).FirstOrDefault();
if(loggerAttribute != null) {
loggerName = loggerAttribute.Name;
}
e.Parameters = e.Parameters.Union(new Parameter[]
{
new ResolvedParameter(
(p, i) => p.ParameterType == typeof (ILogger),
(p, i) =>
{
// If the parameter being injected has its own logger attribute, then promote its name value instead as the logger name to use.
loggerAttribute = (LoggerAttribute)
p.GetCustomAttributes(typeof(LoggerAttribute),true).FirstOrDefault();
if (loggerAttribute != null)
{
loggerName = loggerAttribute.Name;
}
// Return a new Logger instance for injection, parameterised with the most appropriate name which we have determined above.
return LogManager.GetLogger(loggerName);
}),
// Always make an unamed instance of Logger available for use in delegate-based registration e.g.: Register((c,p) => new Foo(p.TypedAs<Logger>())
new TypedParameter(typeof(ILogger), LogManager.GetLogger(loggerName))
});
}
}
public class TestController : ApiController
{
private IUnitOfWork uow;
private ILogger _logger;
// GET api/test
public TestController(IUnitOfWork unitOfWork, ILogger logger) {
uow = unitOfWork;
_logger = logger;
}
...
}
Bootstrapper.cs
public interface ILogger {
void Debug(string message);
void Trace(string message);
void Info(string message);
void Warning(string message);
void Error(string message);
void Error(string message, Exception exception);
void Fatal(string message);
void Fatal(string message, Exception exception);
}
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Class)]
public class LoggerAttribute : Attribute {
public readonly string Name;
public LoggerAttribute(string name) {
Name = name;
}
}
public class NLogger : ILogger {
private readonly NLog.Logger logger;
public NLogger(Type loggerType) {
logger = LogManager.GetLogger(loggerType.FullName);
}
public void Debug(string message) {
logger.Debug(message);
}
public void Trace(string message) {
logger.Trace(message);
}
public void Info(string message) {
logger.Info(message);
}
public void Warning(string message) {
logger.Warn(message);
}
public void Error(string message) {
logger.Error(message);
}
public void Error(string message, Exception exception) {
logger.ErrorException(message, exception);
}
public void Fatal(string message) {
logger.Fatal(message);
}
public void Fatal(string message, Exception exception) {
logger.FatalException(message, exception);
}
}
public class NLogModule : Module {
protected override void AttachToComponentRegistration(IComponentRegistry registry, IComponentRegistration registration) {
registration.Preparing += OnComponentPreparing;
}
static void OnComponentPreparing(object sender, PreparingEventArgs e) {
var typePreparing = e.Component.Activator.LimitType;
// By default, the name supplied to the logging instance is the name of the type in which it is being injected into.
string loggerName = typePreparing.FullName;
//If there is a class-level logger attribute, then promote its supplied name value instead as the logger name to use.
var loggerAttribute = (LoggerAttribute)typePreparing.GetCustomAttributes(typeof(LoggerAttribute), true).FirstOrDefault();
if(loggerAttribute != null) {
loggerName = loggerAttribute.Name;
}
e.Parameters = e.Parameters.Union(new Parameter[]
{
new ResolvedParameter(
(p, i) => p.ParameterType == typeof (ILogger),
(p, i) =>
{
// If the parameter being injected has its own logger attribute, then promote its name value instead as the logger name to use.
loggerAttribute = (LoggerAttribute)
p.GetCustomAttributes(typeof(LoggerAttribute),true).FirstOrDefault();
if (loggerAttribute != null)
{
loggerName = loggerAttribute.Name;
}
// Return a new Logger instance for injection, parameterised with the most appropriate name which we have determined above.
return LogManager.GetLogger(loggerName);
}),
// Always make an unamed instance of Logger available for use in delegate-based registration e.g.: Register((c,p) => new Foo(p.TypedAs<Logger>())
new TypedParameter(typeof(ILogger), LogManager.GetLogger(loggerName))
});
}
}
public class TestController : ApiController
{
private IUnitOfWork uow;
private ILogger _logger;
// GET api/test
public TestController(IUnitOfWork unitOfWork, ILogger logger) {
uow = unitOfWork;
_logger = logger;
}
...
}
var builder=new ContainerBuilder()
//注册Web API控制器。
RegisterAppController(Assembly.getExecutionGassembly());
//注册其他依赖项。
builder.RegisterType();
builder.RegisterType();
RegisterModule(新的NLogModule());
builder.Register((c,p)=>newtestcontroller(p.TypedAs(),p.TypedAs());
//构建容器。
var container=builder.Build();
//创建依赖解析程序。
var resolver=新的AutofacWebApidenceResolver(容器);
//使用依赖项解析程序配置Web API。
GlobalConfiguration.Configuration.DependencyResolver=解析程序;
我无法让它工作,每一次更改都会导致不同的错误
当前代码导致以下错误
<Error>
<Message>An error has occurred.</Message>
<ExceptionMessage>Sequence contains no elements</ExceptionMessage>
<ExceptionType>System.InvalidOperationException</ExceptionType>
<StackTrace>
at System.Linq.Enumerable.First[TSource](IEnumerable`1 source) at Autofac.ParameterExtensions.ConstantValue[TParameter,TValue](IEnumerable`1 parameters, Func`2 predicate) at Autofac.ParameterExtensions.TypedAs[T](IEnumerable`1 parameters) at TestAPI.Bootstrapper.<SetAutofacWebAPIServices>b__0(IComponentContext c, IEnumerable`1 p) in d:\Projects\RadoreAPIs\TestAPI\Bootstrapper.cs:line 32 at Autofac.Builder.RegistrationBuilder.<>c__DisplayClass1`1.<ForDelegate>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) at Autofac.Core.Resolving.InstanceLookup.Execute() at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable`1 parameters) at Autofac.Core.Resolving.ResolveOperation.Execute(IComponentRegistration registration, IEnumerable`1 parameters)
</StackTrace>
</Error>
发生了一个错误。
序列不包含任何元素
System.InvalidOperationException异常
在System.Linq.Enumerable.First[TSource](IEnumerable`1 source)at Autofac.ParameterExtensions.ConstantValue[TParameter,TValue](IEnumerable`1参数,Func`2谓词)at Autofac.ParameterExtensions.TypedAs[T](IEnumerable`1参数)at TestAPI.Bootstrapper.b_u0(IComponentContext c,IEnumerable`1 p)在d:\Projects\radoreapi\TestAPI\Bootstrapper.cs中:Autofac.Builder.RegistrationBuilder.c_uu的第32行显示Autofac.Core.Activators.DelegateActivator.activateInstanceInstance的class1`1.b_u0(IComponentContext c,IEnumerable`1 p)(IComponentContext c,IEnumerable`1 p)Autofac.Core.Resolving.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope,IComponentRegistration registration,IEnumerable`1参数)中的Autofac.Core.Resolving.ResolveOperation.Execute()中的(IEnumerable`1参数)(IComponentRegistration注册,IEnumerable`1参数)
首先,您的NLogModule
将提供ILogger
的实例,因此不需要注册NLogger
(builder.RegisterType().As()
),将其删除
接下来,您是否让模块在没有奇特的[Logger]
属性支持的情况下工作
第三,不要使用
e.Component.Activator.LimitType
作为“声明类型”,而是从参数lambda中使用p.Member.DeclaringType
。请阅读我的答案。谢谢你的答案,但在我应用了你的答案后,我在下面出现了错误:“无法将'NLog.Logger'类型的对象强制转换为'TestAPI.Logging.ILogger'”我不确定,但我认为,Autofac试图将NLog.Logger作为参数发送给控制器以获取ILogger参数。啊,是的,您的模块中有一些错误。我认为您应该使用新的NLogger(…)
而不是LogManager.GetLogger(…)
。依赖关系表明它需要一个类型为ILogger
的服务,这就是模块必须提供的。就是这样。非常感谢,这都是关于新的NLogger(…):)在这里发布之前,我遇到了这个错误,但我无法解决并尝试了其他方法。你救了我一天:)太好了,@bahadirarslan,很高兴为您提供帮助:)