【问题标题】:Using Simple Injector with Umbraco Controller使用带有 Umbraco 控制器的简单注射器
【发布时间】:2016-04-16 14:40:35
【问题描述】:

我正在尝试将依赖项注入到从 Umbraco 的 RenderMvcController 继承的控制器中并得到错误

找不到类型 RenderMvcController 的注册,并且无法进行隐式注册。对于能够创建 RenderMvcController 的容器,它应该只有一个公共构造函数:它有 3 个。有关详细信息,请参阅 https://simpleinjector.org/one-constructor

下面是我连接 DI 的代码

        var container = new Container();
        container.Options.DefaultScopedLifestyle = new WebRequestLifestyle();

        InitializeContainer(container);

        container.RegisterMvcControllers(Assembly.GetExecutingAssembly());

        container.Verify();

        DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));



    private static void InitializeContainer(Container container)
    {
        container.Register<ICacheProvider, CacheProvider>(Lifestyle.Transient);
        container.Register<ICacheService, CacheService>(Lifestyle.Transient);
    }

这是一个接收依赖的类的例子,它继承自我写的一个基类

public class NewsroomController : BaseRenderMvcController
{
    public NewsroomController(ICacheService cacheService) : base(cacheService) { }

基类扩展了作为 Umbraco 控制器的 RenderMvcController

public class BaseRenderMvcController : RenderMvcController
{
    public ICacheService CacheService { get; set; }
    public BaseRenderMvcController(ICacheService cacheService)
    {
        CacheService = cacheService;
    }
}

正如你所见,基本的 Umbraco 控制器实际上有 3 个不同的构造函数

public class RenderMvcController : UmbracoController, IRenderMvcController, IRenderController, IController
{
    public RenderMvcController();
    public RenderMvcController(UmbracoContext umbracoContext);
    public RenderMvcController(UmbracoContext umbracoContext, UmbracoHelper umbracoHelper);

我不确定如何让 SimpleInjector 与从 Umbraco 继承的控制器很好地放置。

提前致谢!

【问题讨论】:

  • 所以这个RenderMvcController 是一个基类,不打算由用户直接调用,如http://mysite/rendermvc?谁定义了这个RenderMvcController?你或者它是另一个图书馆的一部分(比如 Umbraco 本身)?
  • 是的,RenderMvcController 是 Umbraco 自己提供的控制器,它可以从那里继承。
  • 这就是我制作 BaseRenderMvcController 的原因,只是为了有一个我可以控制的基础,但我的基础仍然必须从 RenderMvcController 继承才能让 Umbraco 满意。
  • 我无法想象这个 RenderMvcController 是在 Umbraco 程序集中定义的,因为在这种情况下,控制器不会在容器中注册,因为您只是调用 RegisterMvcControllers(Assembly.GetExecutingAssembly()),这仅仅意味着只有在你的 MVC 项目中定义的控制器才会被注册。你能找出RenderMvcController 存在于哪个程序集中以及是什么原因导致它被注册?
  • 嗯,是的,它在packages\UmbracoCms.Core.7.4.1\lib\umbraco.dll 中,这就是我尝试检查 RenderMvcController 时得到的结果。不过,整个 CMS 都安装在我的主 MVC 项目中。

标签: c# dependency-injection umbraco simple-injector


【解决方案1】:

异常消息“No registration for type RenderMvcController could be found and an implicit registration could be found”表示 RenderMvcController 类型是直接从 Simple Injector 请求的,但尚未注册。控制器类型通常仅由DefaultControllerFactory 请求,并且它仅在收到在其 url 中具有控制器名称的请求时才会请求特定类型,如:http:\\localhost\RenderMvc\3

由于您在 cmets 中声明 RenderMvcController 仅用作基本控制器,因此我怀疑它实际上是由 MVC 请求的。我认为你应该调查一下。

但它确实需要使用这个控制器,你可以像这样在 Simple Injector 中简单地注册它:

container.Register<RenderMvcController>(() => new RenderMvcController());

有一些方法可以覆盖 Simple Injector 的 constructor resolution behavior,但我建议不要这样做,因为它是一个 anti-pattern for components to have multiple constructors。明智的做法是不要在框架类型上使用容器的自动装配行为(如 here 所述),因此建议使用 lambda 注册它们。

【讨论】:

  • 这确实解决了我的问题,虽然我得到了一个错误,它实现了 IDisposable,所以我不得不让它成为 container.Register(() => new RenderMvcController(), Lifestyle.Scoped) ;
  • 我也考虑过你所说的。尽管我必须从控制器继承来覆盖任何自定义路由,但我想 Umbaco 会将该控制器实例用于所有隐式路由,这就是首先调用它的原因。非常感谢您的帮助,并首先感谢您开发图书馆!
猜你喜欢
  • 1970-01-01
  • 2014-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-21
  • 1970-01-01
相关资源
最近更新 更多