2011-08-13 23 views
16

我正在使用Ninject和使用nuget安裝的MVC3擴展。我的內核設置代碼位於App_Start/NinjectMVC3.cs文件中。在控制器中一切都很好,但我無法弄清楚如何(正確地)綁定Global.asax.cs MvcApplication代碼中的接口。在Application_Start中訪問ninject內核

我結束了使用hack(創建一個公共的NinjectMVC3.GetKernel()方法,返回bootstrap.kernel)。然而,這將被棄用,並且必須有一個正確的方法來做到這一點,我沒有看到。

這裏是我的代碼:

public class LogFilterAttribute : ActionFilterAttribute 
{ 
    private IReportingService ReportingService { get; set; } 
    public LogFilterAttribute(IReportingService reportingService) 
    { 
     this.ReportingService = reportingService; 
    } 
    ... 
} 

public class MvcApplication : System.Web.HttpApplication 
{ 
    public static void RegisterGlobalFilters(GlobalFilterCollection filters) 
    { 
     filters.Add(new HandleErrorAttribute()); 
     filters.Add(new LogFilterAttribute() ); 
    } 
    ... 
    protected void Application_Start() 
    { 
     ... 
     RegisterGlobalFilters(GlobalFilters.Filters); 
     // NOTE hack: 
     var kernel = NinjectMVC3.GetKernel(); 
     var logger = kernel.Get<ILogger>(); 
     var bw = new BackgroundWork(logger); 
     Application["BackgroundWork"] = bw; 
     bw.Start(); 
    } 
} 

有兩個接口,我很感興趣,首先是剛剛綁定的對象爲全局變量(ILogger爲BackgroundWork)。

第二個是ActionFilter。我讀http://www.planetgeek.ch/2010/11/13/official-ninject-mvc-extension-gets-support-for-mvc3/,但我沒有看到它如何插入實際註冊(filter.Add)。

我不想使用屬性注入,如果我可以避免它。

任何想法正確的方式來做到這一點? 由於

回答

23

MVC 3介紹了一種填充到一個單的DependencyResolver,和Ninject擴展支持它。

protected void Application_Start() 
{ 
    // ... 
    var logger = DependencyResolver.Current.GetService<ILogger>(); 
} 

現在我應該指出,沒有必要用行動過濾器來做到這一點:如果你需要它,你可以使用你的MvcApplication類。在Ninject.MVC3你應該使用BindFilter語法,就像這樣:

// Declare empty attribute 
public class MyFilterAttribute : FilterAttribute { } 

// Dependency module 
public class MyModule : NinjectModule 
{ 
    public override void Load() 
    { 
     // Other bindings 
     // ... 
     this.BindFilter<MyActionFilter>(FilterScope.Action, 1) 
      .WhenControllerHas<MyFilterAttribute>(); 
    } 
} 

請注意,您必須使用this因爲BindFilter是一個擴展方法,你也有引用Ninject.Web.Mvc.FilterBindingSyntax命名空間。

+1

關於BindFilter,我假設我們使用INSTEAD的filters.add?所以我可以刪除RegisterGlobalFilters中的代碼?但是,現在有兩個地方可以檢查哪個過濾器正在使用?也許我錯過了一些東西。我應該保留過濾器註冊,並有一個默認的構造函數? – teleball

+1

關於DependencyResolver,是不是一個AntiPattern(http://stackoverflow.com/questions/5653783/is-idependencyresolver-an-anti-pattern)和目前的黑客被刪除的原因? – teleball

+0

@user:'RegisterGlobalFilters'用於在每個控制器的每個動作上執行的過濾器。 'BindFilter'語法註冊一個過濾器,當在控制器或動作中找到一個特定的'Attribute'時使用該過濾器;在這個例子中,只要找到MyFilterAttribute,就會導致運行MyFilter。 – Aaronaught