准备一堵代码墙……这是一本很长的书,但我尽其所能。
回应Still lost on Repositories and Decoupling, ASP.NET MVC
我想我将开始更加了解这一切。
我正试图习惯使用它。这是我到目前为止所拥有的。
项目
Project.Web(ASP.NET MVC 3.0 RC)
使用Project.Models
使用Project.Persistence
项目
Project.Models(域对象)Membership.Member
Membership.IMembershipProvider
项目
Project.Persistence(Fluent nHibernate)
使用Project.Models
使用Castle.Core
使用Castle.WindsorMembership.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);
}
所以我首先要问..
我在正确的轨道上吗?
如何为我的ISessionFactory使用Castle.Windsor
我有我的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应用程序中,页面请求的典型入口点是控制器。我们希望Inversion of Control容器能够为我们解析控制器,因为这样,只要将依赖项作为参数在控制器的构造函数中列出,也可以自动解决控制器具有的任何依赖项。
感到困惑了吗?这是所有设置完成后如何使用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);
}
}
请注意,您不必自己进行任何解析,只需在控制器中指定依赖项是什么。您实际上也没有提供任何有关如何实现依赖关系的指示-它们都是分离的。这很简单,这里没有什么复杂的:-)
希望在这一点上您在问,“但是构造函数如何实例化?”这是我们开始设置您的Castle容器的地方,我们完全在MVC Web项目(不是Persistence或Domain)中完成此操作。编辑Global.asax文件,将Castle Windsor设置为控制器工厂:
protected void Application_Start()
{
//...
ControllerBuilder.Current
.SetControllerFactory(typeof(WindsorControllerFactory));
}
...并定义WindsorControllerFactory,以便您的控制器由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正在创建您的控制器,并且提供程序已传递给您的控制器构造函数,因此该提供程序会自动传递给您在Windsor容器中配置的
ISessionFactory
实现!您不必担心再次实例化任何依赖项。您的容器会自动为您完成所有操作。
最后,请注意,
IMembershipProvider
应该定义为域的一部分,因为它正在定义域行为方式的接口。如上所述,处理数据库的域接口的实现已添加到持久层。关于asp.net-mvc - MVC应用程序中的CaSTLe Windsor IoC,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/4401244/