gpt4 book ai didi

asp.net-mvc - MVC 应用程序中的 CaSTLe Windsor IoC

转载 作者:行者123 更新时间:2023-12-02 03:16:45 25 4
gpt4 key购买 nike

准备好一堵代码墙...这是一篇很长的文章,但它已经是我能读到的最详细的内容了。

回应Still lost on Repositories and Decoupling, ASP.NET MVC

认为我开始越来越接近理解这一切。我正在努力习惯使用这个。这是我到目前为止所拥有的。

项目

Project.Web (ASP.NET MVC 3.0 RC)

  • 使用 Project.Models
  • 使用 Project.Persistence

项目

Project.Models (Domain Objects)

  • Membership.Member
  • Membership.IMembershipProvider

项目

Project.Persistence (Fluent nHibernate)

  • 使用 Project.Models
  • 使用 CaSTLe.Core
  • 使用 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 中,我有以下代码。

    protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();

RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);

// Register the Windsor Container
Project.Persistence.IoC.Initialize();
}

现在,在 Project.Web.Controllers.MembershipController 中,我有以下代码。

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

所以我首先问..

我走在正确的道路上吗?

如何将 CaSTLe.Windsor 用于我的 ISessionFactory

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

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

var session = SessionFactoryContainer.Instance.OpenSession()

我已经接近做到这一点了吗?我仍然很困惑 - 我觉得 ISessionFactory 应该是 CaSTLe.Windsor 的一部分,但我似乎不知道该怎么做。我也对在 Controller 中创建存储库的方式感到困惑。这是否意味着每次使用存储库时我都必须执行所有“映射”?这看起来会非常消耗资源。

最佳答案

首先是一些概念细节。在 ASP.NET MVC 应用程序中,页面请求的典型入口点是 Controller 。我们希望控制反转容器为我们解析 Controller ,因为这样 Controller 所具有的任何依赖项也可以通过将依赖项列为 Controller 构造函数中的参数来自动解析。

还困惑吗?这是完成所有设置后如何使用 IoC 的示例。我认为这样解释会让事情变得更容易!

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

请注意,您不必自己进行任何解析,您只需在 Controller 中指定依赖项是什么。您实际上也没有给出任何关于如何实现依赖项的指示 - 它都是解耦的。这很简单,没有什么复杂的:-)

希望此时您会问,“但是构造函数如何实例化?”这是我们开始设置 CaSTLe 容器的地方,并且我们完全在 MVC Web 项目(不是持久性或域)中完成此操作。编辑 Global.asax 文件,将 CaSTLe Windsor 设置为 Controller 工厂:

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

...并定义 WindsorControllerFactory 以便您的 Controller 由 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() 方法是静态单例,返回已配置的 CaSTLe Windsor 容器。容器的配置指示 Windsor 如何解决应用程序的依赖关系。例如,您可能配置了一个容器来解析 NHibernate SessionFactory 和您的 IMembershipProvider。

我喜欢使用多个“安装程序”来配置我的 CaSTLe 容器。每个安装程序负责不同类型的依赖项,因此我有一个 Controller 安装程序、一个 NHibernate 安装程序、一个 Provider 安装程序.

首先我们有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 实例:

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

这应该是足够的代码来开始! 希望你仍然和我在一起,因为城堡容器的美丽很快就会变得明显。

当您在持久层中定义 IMembershipProvider 的实现时,请记住它依赖于 NHibernate ISessionFactory。您需要做的就是:

public class NHMembershipProvider : IMembershipProvider
{
private readonly ISessionFactory sessionFactory;

public NHMembershipProvider(ISessionFactory sessionFactory)
{
this.sessionFactory = sessionFactory;
}
}

请注意,由于 CaSTLe Windsor 正在创建 Controller 并将提供程序传递给 Controller ​​构造函数,因此提供程序将自动传递到 Windsor 容器中配置的 ISessionFactory 实现!

您永远不必担心再次实例化任何依赖项。您的容器会自动为您完成这一切。

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

关于asp.net-mvc - MVC 应用程序中的 CaSTLe Windsor IoC,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4401244/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com