我们目前正在与一个较旧的项目(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();
}
}
老实说,我真的很想使用构造函数注入...
为什么它不能与我们当前的设置一起使用?
是否因为它是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]
属性注入。
我在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…