.NET 4.7.2 ASP.NET WebForms网站中的依赖项注入-构造函数注入不起作用 [英] .NET 4.7.2 Dependency Injection in ASP.NET WebForms Website - Constructor injection not working

查看:64
本文介绍了.NET 4.7.2 ASP.NET WebForms网站中的依赖项注入-构造函数注入不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们目前正在与一个较旧的项目(ASP.NET Web窗体网站)合作,并试图查看是否可以为其设置依赖项注入.

We are currently working with an older project (ASP.NET Web Forms Website) and trying to see if we can set up dependency injection for it.

需要强调的是:这不是Web应用程序项目,而是较旧的类型,即网站.

Need to emphasize: this is NOT a Web Application project... it's the older type, the Website.

当前针对.NET 4.7.2:

It is currently targeting .NET 4.7.2:

<httpRuntime targetFramework="4.7.2" />

到目前为止,我们已经包含了NuGet软件包:

So far, we've included the NuGet package:

<package id="Microsoft.AspNet.WebFormsDependencyInjection.Unity" version="1.0.0" targetFramework="net472" />

定义了一些虚拟接口和实现:

Defined some dummy interface and implementations:

public interface IDependencyTest
{
    string GetName();
}

public class DependencyTest : IDependencyTest
{
    public string GetName()
    {
        return "Mwuhahaha!!!";
    }
}

并将DI容器连接到global.asax的Application_Start事件处理程序中:

And wired the DI container in the Application_Start event handler in global.asax:

void Application_Start(object sender, EventArgs e)
{
    var container = this.AddUnity();

    container.RegisterType<IDependencyTest, DependencyTest>();
}

已导入所需的名称空间:

Required namespaces were imported:

<%@ Import Namespace="Microsoft.AspNet.WebFormsDependencyInjection.Unity" %>
<%@ Import Namespace="Unity" %>

创建了一个测试页Teste.aspx:

Created a test page Teste.aspx:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Teste.aspx.cs" Inherits="Teste" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>    
        <asp:Label ID="lblDisplay" runat="server" Text="No luck..."></asp:Label>    
    </div>
    </form>
</body>
</html>

后面带有以下代码:

public partial class Teste : System.Web.UI.Page
{
    private IDependencyTest _dependencyTest;

    public Teste(IDependencyTest dependencyTest)
    {
        _dependencyTest = dependencyTest;
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        lblDisplay.Text = _dependencyTest.GetName();
    }    
}

所有此设置将失败,并具有以下异常:

All this setup will fail with the following exception:

C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\root\7a04dd72\81815e95\App_Web_teste.aspx.cdcab7d2.rtms4_ja.0.cs(187): error CS7036: There is no argument given that corresponds to the required formal parameter 'dependencyTest' of 'Teste.Teste(IDependencyTest)'

但是,属性注入确实有效:

However, property injection does work:

using Unity.Attributes;

public partial class Teste : System.Web.UI.Page
{
    [Dependency]
    public IDependencyTest DependencyTest { get; set; }    

    protected void Page_Load(object sender, EventArgs e)
    {
        lblDisplay.Text = DependencyTest.GetName();
    }    
}

说实话,我真的很想使用构造函数注入...

To be honest, I'd really like to use the constructor injection...

为什么它不能使用我们当前的设置?

Why isn't it working with our current setup?

是因为它是ASP.NET网站而不是ASP.NET WebApplication吗?

Is it because it's a ASP.NET Website and NOT an ASP.NET WebApplication?

还可以做些什么来使其在这里工作吗?

Can anything be done to get it working here, also?

推荐答案

为什么它不适用于我们当前的设置?

Asp.Net WebForms System.Web.UI.Page的默认配置需要较少参数的构造函数来实例化页面并启动

The default configuration of Asp.Net WebForms the System.Web.UI.Page requires a parameter less constructor to instantiate your page and start the Page Life Cycle.

这就是您尝试使用构造函数依赖注入时收到此错误的原因.

Thats the reason you get this error when try to use Constructor Dependency Injection.

error CS7036: There is no argument given that corresponds to the required formal parameter 'dependencyTest' of 'Teste.Teste(IDependencyTest)'


也可以采取任何措施使它在这里工作吗?

在WebForms的黄金时期,使用Asp.Net WebForms进行依赖注入(DI)并不是很常见,因此很难在官方文档中找到某些东西.

Dependency injection (DI) with Asp.Net WebForms wasn't very commom, on the gold times of WebForms, so is very difficult to find something in the official documentation.

在StackOverflow和Google上进行了一些搜索之后,我发现了一些有用的信息,可以帮助您解决问题.

After some searches on StackOverflow and Google I found some useful information that can help you to solve your problem.

在4.7.2版之前,Asp.Net WebForms不能很好地支持DI

DI wans't very well supported in Asp.Net WebForms until version 4.7.2

因此,如果您使用的是4.7.2之前的版本,并且无法更新为较新的版本,则需要使用 PageHandlerFactory .由于我从未尝试过这样做,所以我希望为您提供指向我找到的两个参考的链接.

So if you are using an older version than 4.7.2, and can't update to a newer version, you will need to use PageHandlerFactory. As I never tried this I prefer to give you the links to the two references I found.

为什么每个人都说当存在PageHandlerFactory和IHttpHandlerFactory时,很难在ASP.NET Web表单中进行依赖注入吗?

ASP.NET Web中的依赖项注入表格

如果您使用的是4.7.2之前的版本,或者可以更改为该版本.您可以使用WebForms更好地支持DI.

If you a using a version newer then 4.7.2, or if you can change to this version. You can use WebForms with a better support for DI.

第1步–实施IServiceProvider.您可以在其中实现自己的DI逻辑,也可以插入其他DI框架,例如团结,Ninject.下面的示例演示如何通过构造函数注入ILog对象.

Step 1 – Implement IServiceProvider. You can implement your own DI logic in it or plug in another DI framework, e.g. Unity, Ninject. The following example demonstrates injecting an ILog object through the constructor.

public class SimpleActivator : IServiceProvider
{
    public object GetService(Type serviceType)
    {
        var ctors = serviceType.GetConstructors();
        ConstructorInfo targetCtor = null;
        foreach (var c in ctors)
        {
            var parameters = c.GetParameters();
            if (parameters.Count() == 1 && parameters[0].ParameterType == typeof(ILog))
            {
                targetCtor = c;
                break;
            }
        }

        if(targetCtor != null)
        {
            return targetCtor.Invoke(new object[] { new DebuggingLoger() });
        }
        else
        {
            return Activator.CreateInstance(
            serviceType,
            BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.CreateInstance,
            null,
            null,
            null);
        }
    }
}

第2步–在Global.asax中设置WebObjectActivator.

Step 2 – Set WebObjectActivator in Global.asax.

public class Global : System.Web.HttpApplication
{        
    public override void Init()
    {
        HttpRuntime.WebObjectActivator = new SimpleActivator();

        base.Init();
    }
}

第3步–在Webform页面中使用依赖注入.

Step 3 – Use Dependency Injection in your Webform page.

public partial class WebForm2 : System.Web.UI.Page
{
    private ILog _log;

    public WebForm2(ILog l)
    {
        _log = l;
    }
}

您可以在此链接中看到此示例以及更多内容: https://devblogs.microsoft.com/dotnet/announcing-the-net-framework-4-7-2/

You can see this examples, and more inflortion about it in this link: https://devblogs.microsoft.com/dotnet/announcing-the-net-framework-4-7-2/

我认为,如果可以迁移到.NetFramework的较新版本,则应尝试实现 IServiceProvider .如果不能,则应该分析 PageHandlerFactory 的实现是否比将来花费比实现更多的时间为您节省了更多时间.如果将来无法为您节省时间,则可以继续进行 [Dependency] 属性注入.

In my opinion if you can move to a newer version of .NetFramework you should try to implement the IServiceProvider. If you can't then you should analyse if the implementation of PageHandlerFactory will save you more time in the future than the time you will expend to implement it. If it will not save you any time in the future you can keep with [Dependency] property injection.

这篇关于.NET 4.7.2 ASP.NET WebForms网站中的依赖项注入-构造函数注入不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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