使用Autofac将log4net注入控制器

Ric*_*rdG 7 c# asp.net-mvc log4net autofac

尝试使用Autofac将log4net类注入我的控制器,但是我得到以下异常:

可以使用可用的服务和参数调用在'MvcApplication6.Controllers.HomeController'类型上找到'公共绑定标志'的构造函数:无法解析构造函数'void .ctor(log4net.ILog)的参数'log4net.ILog logger' ".

我创建了一个模块,Log使用正确的类型注入类:

public class LogInjectionModule : Module
{
    protected override void AttachToComponentRegistration(IComponentRegistry registry, IComponentRegistration registration)
    {
         registration.Preparing += OnComponentPreparing;
    }

    static void OnComponentPreparing(object sender, PreparingEventArgs e)
    {
        var t = e.Component.Activator.LimitType;
        e.Parameters = e.Parameters.Union(new[] 
        { 
            new ResolvedParameter((p, i) => p.ParameterType == typeof(ILog), (p, i) => LogManager.GetLogger(t)) 
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我在我的ASP.NET MVC Application_Start方法中注册该模块:

protected void Application_Start()
{
     ContainerBuilder builder = new ContainerBuilder();
     builder.RegisterControllers(typeof (MvcApplication).Assembly) ;

     var container = builder.Build() ;
     DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); 

     builder.RegisterModule(new LogInjectionModule());

     AreaRegistration.RegisterAllAreas();

     RegisterGlobalFilters(GlobalFilters.Filters);
     RegisterRoutes(RouteTable.Routes);
}
Run Code Online (Sandbox Code Playgroud)

我已经向控制器添加了一个constuctor,它将ILog一个参数作为参数:

namespace MvcApplication6.Controllers
{
   public class HomeController : Controller
   {
      ILog _log;

      public HomeController(ILog logger) 
      {
         _log = logger;
      }

      public ActionResult Index()
      {
         ViewBag.Message = "Welcome to ASP.NET MVC!";

         _log.Info("Log message from Index()");

         return View();
      }

      public ActionResult About()
      {
         _log.Info("Log message from About()");

         return View();
      }
   }
}
Run Code Online (Sandbox Code Playgroud)

我相信我错过了一步,所以任何帮助都会受到赞赏.

Iul*_*scu 12

我不确定这是否会导致您的问题,但您应该调用builder.Build()之前尝试将模块添加到ContainerBuilder中;

像这样的东西:

ContainerBuilder builder = new ContainerBuilder();
builder.RegisterControllers(typeof (MvcApplication).Assembly) ;
builder.RegisterModule(new LogInjectionModule());

var container = builder.Build() ;
DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); 
Run Code Online (Sandbox Code Playgroud)

另一个建议是不注入记录器.通常当我设计一个类时,使用构造函数依赖项,我尝试表达我正在建模的组件的逻辑业务依赖性.日志记录主要是与应用程序正交的实现细节.至少使用log4net,您可以在任何需要使用LogManager.GetLogger(类型)创建的日志记录的类中拥有静态成员.为了便于添加记录器,您可以使用Visual Studio代码段.

  • 我明白你的观点,但我认为这是一个品味的问题.我个人并不关心从日志框架中解耦 - 因为我几乎只使用构造函数注入,所以我很乐意删除任何非概念上所需的依赖.在测试时,我只考虑它只是工作,而不是模拟记录器,而在log4net的情况下,它实际上只是工作.正如我说我明白了纯粹的(恕我直言)查看具有记录器注入的,我不认为这是一个不错的办法 - 我只是觉得它简单直接使用日志框架. (6认同)
  • 关于记录器我不能不同意.为什么你会抛弃DI带来的所有解耦优点,因为逻辑是正交的?例如,如果您直接对日志框架有静态依赖,那么如何正确测试?不,IMO你在这里提出了不好的建议. (5认同)