2016-03-02 42 views
1

我不能让StructureMap注入一个值到的Global.asax.cs文件的MvcApplication的构造。我创建了一个全新且干净的项目,并使用StructureMap.MVC5包生成DependencyResolution子文件夹内的必要结构。StructureMap国际奥委会的Application_Start

我的班级被注入很简单:

namespace SMTest.Models { 
    public interface ITestSM 
    { 
     int OnePlusTwo(); 
    } 
    public class TestSM : ITestSM 
    { 
     public int OnePlusTwo() 
     { 
      return 1 + 2; 
     } 
    } } 

IoC.cs是:

namespace SMTest.DependencyResolution { 
    using StructureMap; 

    public static class IoC { 
     public static IContainer Initialize() { 
      return new Container(c => c.AddRegistry<DefaultRegistry>()); 
     } 
    } 
} 

StructuremapMvc.cs包含:

public static void Start() { 
     IContainer container = IoC.Initialize(); 
     StructureMapDependencyScope = new StructureMapDependencyScope(container); 
     DependencyResolver.SetResolver(StructureMapDependencyScope); 
     DynamicModuleUtility.RegisterModule(typeof(StructureMapScopeModule)); 
    } 

而且DefaultRegistry.cs包含:

public DefaultRegistry() { 
     Scan(
      scan => { 
       scan.TheCallingAssembly(); 
       scan.WithDefaultConventions(); 
       scan.With(new ControllerConvention()); 
      }); 

     For<ITestSM>().Singleton().Use<TestSM>(); 
    } 

我可以很容易地将其注入的HomeController:

public class HomeController : Controller 
{ 
    private ITestSM _testsm; 
    public HomeController(ITestSM testsm):base() 
    { 
     _testsm = testsm; 
    } 

    public ActionResult Index() 
    { 
     return View(); 
    } 

但是,当我尝试这样做,在Global.asax.cs中:

public class MvcApplication : System.Web.HttpApplication 
{ 
    private ITestSM _testsm; 
    public MvcApplication(ITestSM testsm) 
    { 
     _testsm = testsm; 
    } 

    protected void Application_Start() 
    {... 

我得到的错误: 编译器错误信息:CS7036:没有给出的参数对应于'MvcApplication.MvcApplication(ITestSM)'所需的形式参数'testsm'

尽管IoC init触发Application_Start之前,StructuremapMvc.cs:

[assembly: PreApplicationStartMethod(typeof(StructuremapMvc), "Start")] 
[assembly: ApplicationShutdownMethod(typeof(StructuremapMvc), "End")] 

任何想法?

编辑: 我能够把它注入到Global.asax.cs中明确:

protected void Application_EndRequest(object sender, System.EventArgs e) 
    { 
     if (!this.Request.Path.Contains("Content") && !this.Request.Path.Contains("Scripts") && !this.Request.Path.Contains("less")) 
     { 
      ISession currentSession = SMTest.App_StartStructuremapMvc.StructureMapDependencyScope.Container.GetInstance<ISession>(); 
      currentSession.Flush(); 
      currentSession.Close(); 
     } 
    } 

不过,我来到这里的会话不是一个注入控制器,所以我和冲洗关闭错误的数据,将数据留给数据库。

回答

4

不幸的是,这是不可能通过构造函数注入依赖注入你的MvcApplication类。这样做的唯一方法就像您发现的那样,通过其静态实例(也称为Service Locator模式)访问容器。

让我解释一下我为什么是这种情况的了解。

您设置您的容器,然后调用以下行后: DependencyResolver.SetResolver(StructureMapDependencyScope);

该行设置挂钩的IoC容器(在这种情况下,StructureMap)到ASP.NET MVC的依赖解析器。最终充当ASP.NET和你的StructureMap容器​​之间的接口。

当控制器由MVC框架实例化,依赖将通过您DependencyResolver中配置的情况下得到解决。然而在创造你的MvcApplication实例的,依赖不会通过DependencyResolver实例解析。控制器通过DependencyResolver来解决唯一依赖关系的实例类型。最终,这是ASP.NET MVC框架中的一个缺陷(已在ASP.NET Core MVC中纠正)。

除此之外,当调用构造函数时,您的容器甚至没有配置,并且只在调用控制器后调用的Start()方法中配置。

+0

谢谢约瑟夫!这确实看起来像一个缺陷,尤其是因为Application_EndRequest,Application_PostAuthenticateRequest等方法驻留在此MvcApplication类中。 – Rok

+0

是的,我同意。值得庆幸的是,依赖注入在.NET Core MVC中得到了更多的关注。很高兴我能帮上忙! –