.NET 4.7.2 ASP.NET WebForms网站中的依赖项注入-构造函数注入不起作用 - c#

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

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

当前针对的是.NET 4.7.2:

<httpRuntime targetFramework="4.7.2" />

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

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

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

public interface IDependencyTest
{
    string GetName();
}

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

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

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

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

导入了所需的名称空间:

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

创建了一个测试页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();
    }    
}

所有这些设置都会失败,但以下情况除外:

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)'

但是,属性注入确实可以工作:

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();
    }    
}

.NET 4.7.2 ASP.NET WebForms网站中的依赖项注入-构造函数注入不起作用 - c#

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

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

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

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

参考方案

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

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

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

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

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

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

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

直到版本4.7.2,DI才在Asp.Net WebForms中得到很好的支持。

因此,如果您使用的版本早于4.7.2,并且无法更新到较新的版本,则需要使用PageHandlerFactory。因为我从没有尝试过,所以我希望为您提供指向我找到的两个参考的链接。

Why does everyone say dependency injection in ASP.NET webforms is hard when PageHandlerFactory and IHttpHandlerFactory exist?

Dependency Injection in ASP.NET Web Forms

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

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

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。

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

        base.Init();
    }
}

步骤3 –在您的Webform页面中使用依赖注入。

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/

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

ddl在服务器中未更新-asp.net - javascript

我在ASP.NET c#上工作。我有一个DropDownList。 (runat =“ server”)在$ {document).ready上,我更新了它的值:$(document).ready(function () { document.getElementById("ddl").value = "abc"; ……

ASP.net C#崩溃一行 - c#

我有一个母版页,在on load事件中包含以下几行: string menuIDdata = Page.Request.QueryString["mid"]; menuID = 0; // Get the menu ID if (!int.TryParse(menuIDdata, out menuID)) { menuID = 0; } …

ASP.NET-如何更改JSON序列化的方式? - javascript

我正在使用ASP.NET通过以下查询返回Json文件:public ActionResult getTransactionTotals(int itemID) { DBEntities db = new DBEntities(); var query = from trans in db.Transactions // Linq query removed …

ASP.NET MVC中应为DataTable返回哪种数据? - javascript

我想为DataTable中的每个页面创建动态加载信息。我正在尝试遵循以下示例:https://www.datatables.net/manual/server-sidehttps://www.datatables.net/manual/data来自示例的代码:$('#example').DataTable( { serverSide: t…

ASP.net WebForms-如何从代码隐藏获取html5数据属性? - javascript

即时通讯试图从HtmlControl获取数据属性(数据图标)...该数据属性是通过js函数设置的,但是当页面回发时,它返回(在代码后面)一个空字符串有什么办法,任何财产,否则就可以得到它?我的代码:HTML:<button id="btnIcon" runat="server" class="btn b…