温莎城堡国际奥委会MVC应用程序 [英] Castle Windsor IoC in an MVC application

查看:129
本文介绍了温莎城堡国际奥委会MVC应用程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

prepare为code的墙壁......这是一个漫长的读,但它是冗长,因为我可以得到的。

Prepare for a wall of code... It's a long read, but it's as verbose as I can get.

在响应于<一href=\"http://stackoverflow.com/questions/4390489/still-lost-on-repositories-and-decoupling-asp-net-mvc\">Still失去了对库和去耦,ASP.NET MVC

我觉得我开始得到更进一步地理解这一切。
我想习惯使用这个。这里是我到目前为止所。

I think I am starting to get closer to understanding this all. I'm trying to get used to using this. Here is what I have so far.

Project.Web(ASP.NET MVC 3.0 RC)

Project.Web (ASP.NET MVC 3.0 RC)


  • 使用Project.Models

  • 使用Project.Persistence

Project.Models(域对象)

Project.Models (Domain Objects)


  • Membership.Member

  • Membership.IMembershipProvider

  • Membership.Member
  • Membership.IMembershipProvider
  • Project.Persistence(功能NHibernate)

    Project.Persistence (Fluent nHibernate)


    • 使用Project.Models

    • 使用Castle.Core

    • 使用Castle.Windsor

    • Uses Project.Models
    • Uses Castle.Core
    • Uses Castle.Windsor

      Membership.MembershipProvider:IMembershipProvider

      我在 Project.Persistence

      using Castle.Windsor;
      
      using Castle.MicroKernel.Registration;
      using Castle.MicroKernel.SubSystems.Configuration;
      
      namespace Project.Persistence
      {
          public static class IoC
          {
              private static IWindsorContainer _container;
      
              public static void Initialize()
              {
                  _container = new WindsorContainer()
                      .Install(
                          new Persistence.Containers.Installers.RepositoryInstaller()
                  );
              }
      
              public static T Resolve<T>()
              {
                  return _container.Resolve<T>();
              }
          }
      }
      namespace Persistence.Containers.Installers
      {
          public class RepositoryInstaller : IWindsorInstaller
          {
              public void Install(IWindsorContainer container, IConfigurationStore store)
              {
                  container.Register(
                      Component
                      .For<Membership.IMembershipProvider>()
                      .ImplementedBy<Membership.MembershipProvider>()
                      .LifeStyle.Singleton
                  );
              }
          }
      }
      

      现在,在 Project.Web 的Global.asax 的Application_Start ,我有以下的code。

      Now, in Project.Web Global.asax Application_Start, I have the following code.

          protected void Application_Start()
          {
              AreaRegistration.RegisterAllAreas();
      
              RegisterGlobalFilters(GlobalFilters.Filters);
              RegisterRoutes(RouteTable.Routes);
      
              // Register the Windsor Container
              Project.Persistence.IoC.Initialize();
          }
      

      现在然后在 Project.Web.Controllers.MembershipController 我有以下的code。

      Now then, in Project.Web.Controllers.MembershipController I have the following code.

          [HttpPost]
          public ActionResult Register( Web.Models.Authentication.Registration model)
          {
              if (ModelState.IsValid)
              {
                  var provider = IoC.Resolve<Membership.IMembershipProvider>();
                  provider.CreateUser(model.Email, model.Password);
              }
      
              // If we got this far, something failed, redisplay form
              return View(model);
          }
      

      所以我要求首先..

      So I am asking first of all..

      我有我的SessionFactory这样工作...

      I have my SessionFactory working like this ...

      namespace Project.Persistence.Factories
      {
          public sealed class SessionFactoryContainer
          {
              private static readonly ISessionFactory _instance = CreateSessionFactory();
      
              static SessionFactoryContainer()
              { 
      
              }
      
              public static ISessionFactory Instance
              {
                  get { return _instance; }
              }
      
              private static ISessionFactory CreateSessionFactory()
              {
                  return Persistence.SessionFactory.Map(@"Data Source=.\SQLEXPRESS;Initial Catalog=FluentExample;Integrated Security=true", true);
              }
          }
      }
      namespace Project.Persistence
      {
          public static class SessionFactory
          {
              public static ISessionFactory Map(string connectionString, bool createSchema)
              {
                  return FluentNHibernate.Cfg.Fluently.Configure()
                      .Database(FluentNHibernate.Cfg.Db.MsSqlConfiguration.MsSql2008
                          .ConnectionString(c => c.Is(connectionString)))
                          .ExposeConfiguration(config =>
                          {
                              new NHibernate.Tool.hbm2ddl.SchemaExport(config)
                                  .SetOutputFile("Output.sql")
                                  .Create(/* Output to console */ false, /* Execute script against database */ createSchema);
                          })
                          .Mappings(m =>
                          {
                              m.FluentMappings.Conventions.Setup(x =>
                              {
                                  x.AddFromAssemblyOf<Program>();
                                  x.Add(FluentNHibernate.Conventions.Helpers.AutoImport.Never());
                              });
      
                              m.FluentMappings.AddFromAssemblyOf<Mapping.MembershipMap>();
                          }).BuildSessionFactory();
              }
      

      所以基本上,我的 Project.Persistence 层内,我叫了一个SessionFactory这样的..

      So basically, within my Project.Persistence layer, I call the SessionFactory like this..

      var session = SessionFactoryContainer.Instance.OpenSession()
      

      是我甚至越来越接近这样做对吗?我仍然困惑 - 我觉得像 ISessionFactory Castle.Windsor 的一部分,但我不能似乎弄清楚如何做到这一点。我也搞不清楚,我创建了控制器存储库的方式。这是否意味着我必须每个I使用Repository时间做所有的映射的?这似乎是这将是非常耗费资源。

      Am I even getting close to doing this right? I'm still confused - I feel like the ISessionFactory should be part of Castle.Windsor, but I can't seem to figure out how to do that. I'm confused also about the way I am creating the Repository in the Controller. Does this mean I have to do all of the 'mapping' each time I use the Repository? That seems like it would be very resource intensive.

      推荐答案

      一是一些概念性的细节。在ASP.NET MVC应用程序典型的切入点页面请求是控制器。我们希望控制容器的反转来解决我们的控制器对我们来说,因为当时该控制器具有任何相关性还可以自动通过简单地列出依赖作为控制器的构造参数解决。

      Firstly some conceptual details. In an ASP.NET MVC application the typical entry point for a page request is a controller. We want the Inversion of Control container to resolve our controllers for us, because then any dependencies that the controllers have can also be automatically resolved simply by listing the dependencies as arguments in the controllers' constructors.

      困惑了吗?下面是你如何使用IoC的,之后它都设立了一个例子。我想解释这种方式让事情变得更容易!

      Confused yet? Here's an example of how you'd use IoC, after it is all set up. I think explaining it this way makes things easier!

      public class HomeController : Controller
      {
          // lets say your home page controller depends upon two providers
          private readonly IMembershipProvider membershipProvider;
          private readonly IBlogProvider blogProvider;
      
          // constructor, with the dependencies being passed in as arguments
          public HomeController(
                      IMembershipProvider membershipProvider,
                      IBlogProvider blogProvider)
          {
              this.membershipProvider = membershipProvider;
              this.blogProvider = blogProvider;
          }
      
          // so taking your Registration example...
          [HttpPost]
          public ActionResult Register( Web.Models.Authentication.Registration model)
          {
              if (ModelState.IsValid)
              {
                  this.membershipProvider.CreateUser(model.Email, model.Password);
              }
      
              // If we got this far, something failed, redisplay form
              return View(model);
          }
      }
      

      请注意,你还没有做任何解决你自己,你刚才在控制器哪些依赖是指定的。也没有你居然给出如何的依赖关系实现的任何迹象 - 这是所有的脱钩的。这很简单,没​​有什么复杂在这里: - )

      Note that you have not had to do any resolving yourself, you have just specified in the controller what the dependencies are. Nor have you actually given any indication of how the dependencies are implemented - it's all decoupled. It's very simple there is nothing complicated here :-)

      希望在这一点上,你都在问,但如何构造函数被实例化?这是我们开始建立你的城堡容器,我们在 MVC的Web 项目做到这一点完全的(不持久或域)的。编辑Global.asax文件,设置温莎城堡作为控制器工厂:

      Hopefully at this point you are asking, "but how does the constructor get instantiated?" This is where we start to set up your Castle container, and we do this entirely in the MVC Web project (not Persistence or Domain). Edit the Global.asax file, setting Castle Windsor to act as the controller factory:

      protected void Application_Start()
      {
      //...   
          ControllerBuilder.Current
              .SetControllerFactory(typeof(WindsorControllerFactory));
      }
      

      ...,定义WindsorControllerFactory使您的控制器由温莎实例:

      ...and define the WindsorControllerFactory so that your controllers are instantiated by Windsor:

      /// Use Castle Windsor to create controllers and provide DI
      public class WindsorControllerFactory : DefaultControllerFactory
      {
          private readonly IWindsorContainer container;
      
          public WindsorControllerFactory()
          {
              container = ContainerFactory.Current();
          }
      
          protected override IController GetControllerInstance(
              RequestContext requestContext,
              Type controllerType)
          {
              return (IController)container.Resolve(controllerType);
          }
      }
      

      ContainerFactory.Current()方法是返回一个配置的温莎城堡容器静态单。容器的配置指导温莎有关如何解决应用程序的依赖。因此,例如,你可能有配置为解决NHibernate的SessionFactory的,和你的IMembershipProvider的容器。

      The ContainerFactory.Current() method is static singleton that returns a configured Castle Windsor container. The configuration of the container instructs Windsor on how to resolve your application's dependencies. So for example, you might have a container configured to resolve the NHibernate SessionFactory, and your IMembershipProvider.

      我要配置使用多个安装程序我的城堡容器。每个安装人员负责不同类型的依赖,所以我有一个的控制器的安装程序,一个的 NHibernate的的安装程序,一个的提供的例如安装程序

      I like to configure my Castle container using several "installers". Each installer is responsible for a different type of dependency, so I'd have a Controller installer, an NHibernate installer, a Provider installer for example.

      首先,我们有ContainerFactory通过:

      Firstly we have the ContainerFactory:

      public class ContainerFactory
      {
          private static IWindsorContainer container;
          private static readonly object SyncObject = new object();
      
          public static IWindsorContainer Current()
          {
              if (container == null)
              {
                  lock (SyncObject)
                  {
                      if (container == null)
                      {
                          container = new WindsorContainer();
                          container.Install(new ControllerInstaller());
                          container.Install(new NHibernateInstaller());
                          container.Install(new ProviderInstaller());
                      }
                  }
              }
              return container;
          }
      }
      

      ...然后,我们需要每个安装的。在 ControllerInstaller 第一:

      public class ControllerInstaller : IWindsorInstaller
      {
          public void Install(IWindsorContainer container, IConfigurationStore store)
          {
              container.Register(
                  AllTypes
                      .FromAssembly(Assembly.GetExecutingAssembly())
                      .BasedOn<IController>()
                      .Configure(c => c.Named(
                          c.Implementation.Name.ToLowerInvariant()).LifeStyle.PerWebRequest));
          }
      }
      

      ...这里是我的 NHibernateInstaller 虽然它是你不一样,你可以用你自己的配置。请注意,我重复使用相同的 ISessionFactory 实例,每次一个解决:

      ... and here is my NHibernateInstaller although it is different to yours, you can use your own configuration. Note that I'm reusing the same ISessionFactory instance every time one is resolved:

      public class NHibernateInstaller : IWindsorInstaller
      {
          private static ISessionFactory factory;
          private static readonly object SyncObject = new object();
      
          public void Install(IWindsorContainer container, IConfigurationStore store)
          {
              var windsorContainer = container.Register(
                  Component.For<ISessionFactory>()
                      .UsingFactoryMethod(SessionFactoryFactory));
          }
      
          private static ISessionFactory SessionFactoryFactory()
          {
              if (factory == null)
              {
                  lock (SyncObject)
                  {
                      if (factory == null)
                      {
                          var cfg = new Configuration();
                          factory = cfg.Configure().BuildSessionFactory();
                      }
                  }
              }
      
              return factory;
          }
      }
      

      最后,你会想定义你的 ProvidersInstaller

      public class ProvidersInstaller : IWindsorInstaller
      {
          public void Install(IWindsorContainer container, IConfigurationStore store)
          {
              var windsorContainer = container
                  .Register(
                      Component
                          .For<IMembershipProvider>()
                          .ImplementedBy<SubjectQueries>())
                  .Register(
                      Component
                          .For<IBlogProvider>()
                          .ImplementedBy<SubjectQueries>());
      
                  // ... and any more that your need to register
          }
      }
      

      这应该是足够的code起来啦! 希望你还是跟我的城堡容器的美变得明显很快。

      This should be enough code to get going! Hopefully you're still with me as the beauty of the Castle container becomes apparent very shortly.

      当你在你的持久层定义的执行你的 IMembershipProvider ,请记住,它对NHibernate的 ISessionFactory 。所有你需要做的是这样的:

      When you define your implementation of your IMembershipProvider in your persistence layer, remember that it has a dependency on the NHibernate ISessionFactory. All you need to do is this:

      public class NHMembershipProvider : IMembershipProvider
      {
          private readonly ISessionFactory sessionFactory;
      
          public NHMembershipProvider(ISessionFactory sessionFactory)
          {
              this.sessionFactory = sessionFactory;
          }
      }
      

      请注意,由于温莎城堡是创建你的控制器,并传递给你的控制器构造提供者,提供者将自动被传递在温莎容器配置的 ISessionFactory 执行!

      Note that because Castle Windsor is creating your controllers and the providers passed to your controller constructor, the provider is automatically being passed the ISessionFactory implementation configured in your Windsor container!

      您永远不必再担心实例化的依赖。您的容器做这一切自动为您。

      You never have to worry about instantiating any dependencies again. Your container does it all automatically for you.

      最后,请注意, IMembershipProvider 应定义为您的域的一部分,因为它是定义如何您的域名行为的接口。如上所述,它处理数据库域接口的实现将被添加到持久层。

      Finally, note that the IMembershipProvider should be defined as part of your domain, as it is defining the interface for how your domain behaviours. As noted above, the implementation of your domain interfaces which deal with databases are added to the persistence layer.

      这篇关于温莎城堡国际奥委会MVC应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆