【问题标题】:SimpleInjector and custom WebViewPageSimpleInjector 和自定义 WebViewPage
【发布时间】:2017-08-01 23:35:42
【问题描述】:

我有一个自定义的WebViewPage,我希望 SimpleInjector 解决其中的一些依赖关系。由于 MVC 实例化此类的方式,我似乎无法使用构造函数注入。

我已启用显式属性注入,如 SimpleInjector documentation 中所述。但是属性没有被注入——它们总是null

自定义 WebViewPage 类:

public abstract class CustomWebViewPage<T> : WebViewPage<T>
{
   [Import]
   public IMyDependency Dependency { get; set; }

   public void UseDependency()
   {
      Dependency.DoStuff(); // Dependency is null
   }
}

IOC 设置:

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

container.RegisterMvcControllers(Assembly.GetExecutingAssembly());

container.Register<IMyDependency, MyDependency>();

我是否需要连接其他任何东西才能使其正常工作?我尝试使用 SimpleInjector 注册自定义 WebViewPage(将 WebViewPage&lt;&gt; 映射到 CustomWebViewPage&lt;&gt; 并使我的课程非抽象),但这也不起作用。

需要明确的是,所有其他属性和构造函数依赖注入都在应用程序中工作 - 只是不适用于这个特定的类。

【问题讨论】:

  • 有这个相关的问题 - stackoverflow.com/questions/38704650 - 但这是关于在视图中使用自定义 WebViewPage 类的内容。这一点对我来说很好,但不是属性注入。
  • 如果我没有理解错 - 你是说 MVC 不允许构造函数注入???(因为我只通过构造函数注入控制器的依赖项)
  • It seems like I can't use constructor injection due to the way MVC instantiates this class 这很奇怪。你看过这个吗? :stackoverflow.com/questions/19925290/…
  • @Rudresha - 是的,当然 MVC 允许构造函数注入,我在所有控制器中都使用它。但它似乎不适用于自定义 WebViewPage 类。不过,我很可能做错了什么。
  • 你考虑过这句话吗:But as the others said you shouldn't do view injection anyway. Your view should be dumb and just render the view model to HTML. Anything requiring a dependency should be done in the controller or a service.?

标签: c# asp.net-mvc-4 simple-injector


【解决方案1】:

我同意Remo Gloor's answer 和 Stefan 的声明:

但是正如其他人所说,您无论如何都不应该进行视图注入。您的视图应该是愚蠢的,只是将视图模型呈现为 HTML。任何需要依赖的事情都应该在控制器或服务中完成。

也就是说,如果你真的、真的、真的需要这个(你不应该),我认为这是创建自定义 IViewEngine 的问题。

警告:下面的代码不是!!!全部经过测试*

internal class PropertyInjectionViewEngineDecorator : IViewEngine
{
    private readonly ConcurrentDictionary<Type, Registration> registrations = new ConcurrentDictionary<Type, Registration>();

    private readonly IViewEngine decoratee;
    private readonly Func<Type, Registration> createRegistration;

    public PropertyInjectionViewEngineDecorator(IViewEngine decoratee, Container container)
    {
        this.decoratee = decoratee;
        this.createRegistration = type => Lifestyle.Transient.CreateRegistration(type, container);
    }

    public ViewEngineResult FindPartialView(ControllerContext context, string partialViewName, bool useCache) =>
        this.InitializeView(this.decoratee.FindPartialView(context, partialViewName, useCache));

    public ViewEngineResult FindView(ControllerContext context, string viewName, string masterName, bool useCache) =>
        this.InitializeView(this.decoratee.FindView(context, viewName, masterName, useCache));

    public void ReleaseView(ControllerContext controllerContext, IView view) =>
        this.decoratee.ReleaseView(controllerContext, view);

    private ViewEngineResult InitializeView(ViewEngineResult result)
    {
        if (result.View != null)
        {
            Registration registration = this.registrations.GetOrAdd(result.View.GetType(), this.createRegistration);
            registration.InitializeInstance(result.View);
        }

        return result;
    }
}

您可以将这个自定义 PropertyInjectionViewEngineDecorator 挂接到 MVC 管道中,如下所示:

var razor = ViewEngines.Engines.Single(e => e.GetType() == typeof(RazorViewEngine));
ViewEngines.Engines.Remove(razor);
ViewEngines.Engines.Add(new PropertyInjectionViewEngineDecorator(razor, container));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-02
    • 2012-06-15
    • 2011-12-28
    • 1970-01-01
    • 2013-09-06
    • 1970-01-01
    • 2013-07-29
    相关资源
    最近更新 更多