为什么大家都在说ASP.NET WebForms的依赖注入是很难当PageHandlerFactory和IHttpHandlerFactory存在吗? [英] Why does everyone say dependency injection in ASP.NET webforms is hard when PageHandlerFactory and IHttpHandlerFactory exist?

查看:163
本文介绍了为什么大家都在说ASP.NET WebForms的依赖注入是很难当PageHandlerFactory和IHttpHandlerFactory存在吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我有一个传统的web表单网站,并正在致力于使其更易于维护。夹紧它扔掉,改写它不是一个选项。

So I have a legacy webforms site and am working on making it easier to maintain. Chucking it away and rewriting it isn't an option.

国际奥委会显然是它得到的第一件事情之一,但是这给我留下了服务定位器模式和不好的味道,和它是否可以做更好的疑惑。

IoC is obviously one of the first things it got, but this leaves me with the service-locator pattern and a bad taste, and the wondering of whether it could be done better.

各种各样的人,我已经说过了在线和离线告诉我,我可以做财产注射,扫描饰有一个属性注入或类似房产Page类的HTTP模块,而是这听起来像一个反射命中(缓存,但仍然)在每次请求。没有吸引力。

Various people I've talked to online and off tell me that I could do property-injection with an HttpModule that scans a Page class for properties decorated with an Inject attribute or similar, but that sounds like a Reflection hit (cached, but still) on every request. Not appealing.

所以我一直在寻找其他的选择,并且碰到<一个href=\"http://msdn.microsoft.com/en-us/library/ms227439%28v=VS.85%29.aspx\">System.Web.IHttpHandlerFactory,这显然​​已经在自V2的框架。人们可以删除默认的*的.aspx处理程序,并与使用自定义实现,在web.config中HttpHandlers的部分进行更换。

So I was looking at other options, and came across System.Web.IHttpHandlerFactory, which has apparently been in the framework since v2. One can remove the default *.aspx handler and replace it with one that uses a custom implementation, in httpHandlers web.config section.

所以,我接触过的人都没有哑;我想我会在这里问。 是否有与更换的WebForms任何陷阱PageHandlerFactory与基于IoC容器的实现...?

So, the people I've talked to aren't dumb; I thought I'd ask here. Are there any gotchas with replacing the webforms PageHandlerFactory with an IoC-based implementation...?

它看起来既有CreateHandler和ReleaseHandler方法,所以从容器保持参照创建的组件生活方式相关的内存泄漏不应该是一个问题...

It looks like it has both a CreateHandler and ReleaseHandler method, so life-style related memory leaks from the container keeping a reference to created components shouldn't be a problem...

推荐答案

设计,类需要有一个默认的构造函数。当你想使用构造器注入,有办法解决。您可以保护默认的构造函数,并添加一个公共构造函数的依赖关系如下:

Because of the way ASP.NET is designed, Page classes need to have a default constructor. When you want to use constructor injection, there is a way around this. You can make the default constructor protected and add a single public constructor that takes the dependencies as follows:

public partial class _Default : System.Web.UI.Page
{
    private IUserService service;

    protected _Default()
    {
    }

    public _Default(IUserService service)
    {
        this.service = service;
    }
}

这允许你创建一个自定义的 PageHandlerFactory ,并在构造函数中注入的依赖关系。

This allows you to create a custom PageHandlerFactory and inject the dependencies in the constructor.

所以这个工作,但有一个陷阱,但。您定义的 _Default 类不是实际的类ASP.NET使用。 ASP.NET创建从 _Default 继承了一个新类。这个新的类构建基于.aspx文件的标记控制层次。这个类看起来有点像这样:

So this works, but there is a catch though. The _Default class you define is not the actual class ASP.NET uses. ASP.NET creates a new class that inherits from _Default. This new class builds a control hierarchy based on the markup in the .aspx file. This class looks a bit like this:

public class ASPGeneratedDefault : _Default
{
    public ASPGeneratedDefault() : base()
    {
    }

     protected override void OnPreInit(object s, EventArgs e)
     {
          // Building up control hierarchy.
     }
}

正如你可以看到,自定义构造函数没有被覆盖在 ASPGeneratedDefault 由ASP.NET。正因为如此,没有让一个DI框架,为我们创造这种类型的方式。解决这个问题的办法是让ASP.NET为我们创建这种类型,并调用 _Default 基类的非默认构造函数上现有的实例。因为这种情况已经存在,我们必须反思这样做,在部分信任模式下运行时,这将失败。

As you can see, the custom constructor hasn't been overridden in the ASPGeneratedDefault by ASP.NET. Because of this there is no way of letting a DI framework create this type for us. The way around this is to let ASP.NET create this type for us and invoke the non-default constructor of the _Default base class on that existing instance. Because this instance already exists, we must do this with reflection and this will fail when run in partial trust.

除此之外,这适用于页类,但不适合在页面上的用户控件。 ASP.NET的新闻与控制层次建立过程中,其默认的构造函数这些控件code发生器。当你想这个为他们工作,需要您自定义的 PageHandlerFactory 勾到的 preINIT 事件这些控制,因为在当时的页面类构造,相关控制和用户控件尚未创建。但是,对他们注册 preINIT 事件,你需要找到的网页类中这些控件,并再次我们需要反思在页面类。由于控制存储在非公共实例字段,这同样不会在部分信任的工作。

Besides that, this works for page classes, but not for user controls on the page. The code generator of ASP.NET news up those controls with their default constructor during the control hierarchy build up process. When you want this to work for them, you need your custom PageHandlerFactory to hook to the PreInit event of those controls, because during the time the page class is constructed, the related controls and user controls are not yet created. However, to register the PreInit event on them, you need to find those controls within the page class, and again we need to reflect over the page class. Because controls are stored in non-public instance fields, again this won't work in partial trust.

它是否是一个问题,您的应用程序不能在部分信任运行的是你的,但因为.NET 4的安全模型已经大大简化,这是很容易在部分信任运行Web应用程序,它是我努力做的。

Whether or not it is a problem your application can not run in partial trust is up to you, but since the security model of .NET 4 has been simplified considerably, it is very easy to run web apps in partial trust and it is something I strive to do.

TLDR ;因此,在结束时,有可能这样做(例如参见这个例子),但因为ASP.NET Web窗体框架的限制,需要在完全信任运行得到它的工作。

TLDR; So in conclusion, it is possible to do so (see for instance this example), but because of the limitations of the ASP.NET Web Forms framework, you need to run in full trust to get it to work.

更新开始NET 4.0 ASP.NET微软已经过时,部分信任(读<一个href=\"https://stackoverflow.com/questions/16849801/is-trying-to-develop-for-medium-trust-a-lost-cause\">here).所以从这个角度来看,从完全信任防范可能不是很有用(你会需要它反正)。

UPDATE Microsoft has obsoleted partial trust for ASP.NET starting with NET 4.0 (read here). So from that point of view, keeping away from full trust might not be that useful (you'll need it anyway).

这篇关于为什么大家都在说ASP.NET WebForms的依赖注入是很难当PageHandlerFactory和IHttpHandlerFactory存在吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆