具有统一性的Sitecore DI
我正在尝试建立一个全新的Sitecore 7.2网站,我希望将MVC 5、Glass Mapper和Microsoft Unity集成为DI容器,Sitecore不想玩得很好 我的设想是: 获得了一个名为PoC.Quotes.Web的Web项目-它将只包含CSS、HTML和任何其他资产,而不包含控制器 获得一个名为PoC.Quotes.Controllers的类库项目-这只包含控制器 获得了一个名为PoC.Quotes.DataLayer的类库项目-它包含一个接口ISitecoreRepository及其具体实现SitecoreRepository SitecoreRepository类有一个构造函数,它接收1个参数,Glass Mapper上下文,我的一个控制器在构造函数中接收1个参数…ISitecoreRepository Sitecore存储库类:具有统一性的Sitecore DI,sitecore,inversion-of-control,sitecore7.2,glass-mapper,sitecore-mvc,Sitecore,Inversion Of Control,Sitecore7.2,Glass Mapper,Sitecore Mvc,我正在尝试建立一个全新的Sitecore 7.2网站,我希望将MVC 5、Glass Mapper和Microsoft Unity集成为DI容器,Sitecore不想玩得很好 我的设想是: 获得了一个名为PoC.Quotes.Web的Web项目-它将只包含CSS、HTML和任何其他资产,而不包含控制器 获得一个名为PoC.Quotes.Controllers的类库项目-这只包含控制器 获得了一个名为PoC.Quotes.DataLayer的类库项目-它包含一个接口ISitecoreReposit
public class SitecoreRepository : ISitecoreRepository
{
ISitecoreContext sitecoreContext = null;
public SitecoreRepository(ISitecoreContext context)
{
this.sitecoreContext = context;
}
}
控制器类:
public class HomeController : Controller
{
private ISitecoreRepository _repository;
public HomeController(ISitecoreRepository repository)
{
this._repository = repository;
}
}
每次我运行项目Sitecore时,都会抛出一个错误,说明它无法创建类型为PoC.Quotes.Controllers.HomeController、PoC.Quotes.Controllers的控制器。我猜它显示了完全限定的名称,因为这就是我在控制器渲染中设置它的方式
第一个问题是控制器构造函数参数。我取出它并使用以下语句获取存储库的实例:
System.Web.Mvc.DependencyResolver.Current.GetService<ISitecoreRepository>();
然而,如果我进入Sitecore并将该属性更改为“仅在家”,那么一切都是好的。我甚至尝试过使用PoC.Quotes.Controllers.Home的临时版本,但仍然出现了一个错误,请注意另一个错误
不确定我是否做错了什么,但感觉有点奇怪
有没有办法解决这个问题?虽然我不知道您的注册是如何配置的,但听起来您最好还是选择控制器工厂。温莎就是一个例子,但你可以很容易地在Unity中交换。为了不修改Global.asax,还可以使用WebActivatex连接引导启动 引导器 控制器厂
在这方面花了相当多的时间,并设法提出了一个解决方案。在这里写有点长,所以我把它放在了博客上 基本上,这不是Unity或其他DI容器的问题,而是Sitecore如何处理完全限定名。是的,我知道理想情况下,您不想使用这些名称,而是要遵循MVC模式,但我在博客文章中解释了为什么要使用完全限定的名称 作为高级解释,问题存在于两个Sitecore类ControllerRunner和SitecoreControllerFactory中。这两个类都包含一些方法,这些方法标识完全限定名,并使用反射调用无参数构造函数来实例化新实例。我应用的修复覆盖了这些方法来调用控制器工厂 谢谢你提供的帮助
安德烈你好,吉姆,谢谢你的回复。我的unity配置非常简单,添加了ISitecoreRepository接口和ISitecoreContext Glass映射器接口的配置。我之前曾尝试过温莎城堡工厂,如您在示例中所示,但也遇到了同样的问题。能否在引导代码中设置断点以验证Global.asax或WebActivator是否在Sitecore中工作?在对Sitecore.MVC进行了几个小时的反编译后,我得出结论,问题在于我在Sitecore中为控制器指定的名称。如果我只是用家作为名字,一切都是完美的。使用完全限定名后,Sitecore使用反射实例化新对象并查找无参数构造函数。我仍在研究它,因为它似乎是一个限制使用完全限定的名称,这是ASP.NETMVC相关的。任何帮助或想法都是正确的。对于Sitecore中的渲染,不应将控制器后缀添加到控制器字段a.k.a“无完全限定名”。
PoC.Quotes.Controllers.HomeController, PoC.Quotes.Controllers
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(Site.Website.Cms.WindsorConfig), "RegisterComponents")]`
[assembly: WebActivatorEx.ApplicationShutdownMethod(typeof(Site.Website.Cms.WindsorConfig), "ReleaseComponents")]
/// <summary>
/// Provides a bootstrapping and resolving hook for dependency resolution for MVC, Web API, and service locator.
/// </summary>
public static class WindsorConfig
{
private static Lazy<IWindsorContainer> _container;
static WindsorConfig()
{
_container = new Lazy<IWindsorContainer>(() => BuildContainer());
}
public static IWindsorContainer WindsorContainer
{
get
{
return _container.Value;
}
}
/// <summary>
/// Generates and configures the container when the application is started.
/// </summary>
public static void RegisterComponents()
{
ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(WindsorContainer));
GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerActivator), new WindsorControllerActivator(WindsorContainer));
}
/// <summary>
/// Disposes of the container when the application is shut down.
/// </summary>
public static void ReleaseComponents()
{
WindsorContainer.Dispose();
}
}
/// <summary>
/// Provides controller dependency resolving for ASP.NET MVC controllers.
/// </summary>
public class WindsorControllerFactory : DefaultControllerFactory
{
private readonly IWindsorContainer _container;
public WindsorControllerFactory(IWindsorContainer container)
{
if (container == null) throw new ArgumentNullException("container");
this._container = container;
}
public override void ReleaseController(IController controller)
{
this._container.Release(controller);
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
{
throw new HttpException(404, string.Format("The controller for path '{0}' could not be found.", requestContext.HttpContext.Request.Path));
}
return (IController)this._container.Resolve(controllerType);
}
}