SimpleInjector和自定义WebViewPage

时间:2017-08-01 14:04:15

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

我有一个自定义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<>映射到CustomWebViewPage<>并使我的类非抽象),但这也不起作用。

为了清楚起见,所有其他属性和构造函数依赖注入都在应用程序中工作 - 只是不适用于这个特定的类。

1 个答案:

答案 0 :(得分: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));