4

我正在尝试使用 Autofac 添加 NLog 我的 Web Api 项目。但我有问题。

从 NuGet 安装 NLog 包后,我将以下文件添加到我的项目中。(由于关注不同的帖子和示例,可能会造成混淆)

ILogger.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);
    }

记录器属性.cs

[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Class)]
    public class LoggerAttribute : Attribute {
        public readonly string Name;

        public LoggerAttribute(string name) {
            Name = name;
        }
    }

NLogger.cs

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);
        }
    }

NLogModule.cs

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))
        });
        }
    }

测试控制器.cs

 public class TestController : ApiController
    {
        private IUnitOfWork uow;
        private ILogger _logger;
        // GET api/test
        public TestController(IUnitOfWork unitOfWork, ILogger logger) {
            uow = unitOfWork;
            _logger = logger;
        }
...
    }

引导程序.cs

var builder = new ContainerBuilder();

    // Register the Web API controllers.
    builder.RegisterApiControllers(Assembly.GetExecutingAssembly());

    // Register other dependencies.

    builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().InstancePerApiRequest();
    builder.RegisterType<NLogger>().As<ILogger>().InstancePerApiRequest();
    builder.RegisterModule(new NLogModule());
    builder.Register((c, p) => new TestController(p.TypedAs<UnitOfWork>(), p.TypedAs<NLogger>()));
    // Build the container.
    var container = builder.Build();

    // Create the depenedency resolver.
    var resolver = new AutofacWebApiDependencyResolver(container);

    // Configure Web API with the dependency resolver.
    GlobalConfiguration.Configuration.DependencyResolver = resolver;

我无法让它工作,每一个变化都会导致不同的错误。

当前代码导致以下错误。

<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>
4

1 回答 1

7

首先,您NLogModule将提供这样的实例,ILogger因此NLogger( builder.RegisterType<NLogger>().As<ILogger>()) 注册应该是不必要的(并且可能会导致麻烦)。去掉它。

接下来,你有没有让模块在没有花哨的[Logger]属性支持的情况下工作?

第三,不要e.Component.Activator.LimitType用作“声明类型” ,而是p.Member.DeclaringType在参数 lambda 中使用。阅读我对这个相关问题的回答。

于 2013-01-28T13:25:01.700 回答