Mih*_*tea 11 .net c# asp.net dependency-injection webforms
我们目前正在处理一个较旧的项目(ASP.NET Web 窗体网站)并尝试查看是否可以为其设置依赖项注入。
需要强调的是:这不是一个 Web 应用程序项目......它是旧类型的网站。
它目前的目标是 .NET 4.7.2:
<httpRuntime targetFramework="4.7.2" />
Run Code Online (Sandbox Code Playgroud)
到目前为止,我们已经包含了 NuGet 包:
<package id="Microsoft.AspNet.WebFormsDependencyInjection.Unity" version="1.0.0" targetFramework="net472" />
Run Code Online (Sandbox Code Playgroud)
定义了一些虚拟接口和实现:
public interface IDependencyTest
{
string GetName();
}
public class DependencyTest : IDependencyTest
{
public string GetName()
{
return "Mwuhahaha!!!";
}
}
Run Code Online (Sandbox Code Playgroud)
并在 global.asax 中的 Application_Start 事件处理程序中连接 DI 容器:
void Application_Start(object sender, EventArgs e)
{
var container = this.AddUnity();
container.RegisterType<IDependencyTest, DependencyTest>();
}
Run Code Online (Sandbox Code Playgroud)
导入了所需的命名空间:
<%@ Import Namespace="Microsoft.AspNet.WebFormsDependencyInjection.Unity" %>
<%@ Import Namespace="Unity" %>
Run Code Online (Sandbox Code Playgroud)
创建了一个测试页面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>
Run Code Online (Sandbox Code Playgroud)
后面有以下代码:
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();
}
}
Run Code Online (Sandbox Code Playgroud)
所有这些设置都将失败,但出现以下异常:
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)'
Run Code Online (Sandbox Code Playgroud)
但是,属性注入确实有效:
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();
}
}
Run Code Online (Sandbox Code Playgroud)
老实说,我真的很想使用构造函数注入...
为什么它不适用于我们当前的设置?
是因为它是 ASP.NET 网站而不是 ASP.NET WebApplication 吗?
有什么办法可以让它在这里工作吗?
Lut*_*lho 11
为什么它不适用于我们当前的设置?
Asp.Net WebForms 的默认配置 System.Web.UI.Page 需要一个无参数构造函数来实例化页面并启动页面生命周期。
这就是尝试使用构造函数依赖注入时出现此错误的原因。
error CS7036: There is no argument given that corresponds to the required formal parameter 'dependencyTest' of 'Teste.Teste(IDependencyTest)'
Run Code Online (Sandbox Code Playgroud)
有什么办法可以让它在这里工作吗?
Asp.Net WebForms 的依赖注入(DI)在 WebForms 的黄金时代并不是很常见,所以很难在官方文档中找到一些东西。
在 StackOverflow 和 Google 上进行了一些搜索后,我找到了一些可以帮助您解决问题的有用信息。
直到 4.7.2 版,Asp.Net WebForms 才很好地支持 DI
因此,如果您使用的是 4.7.2 之前的版本,并且无法更新到较新的版本,则需要使用PageHandlerFactory. 由于我从未尝试过,因此我更愿意为您提供我找到的两个参考文献的链接。
当PageHandlerFactory和IHttpHandlerFactory存在时,为什么每个人都说ASP.NET webforms中的依赖注入很难?
如果您使用比 4.7.2 更新的版本,或者您可以更改到此版本。您可以使用 WebForms 更好地支持 DI。
步骤 1 – 实施 IServiceProvider。您可以在其中实现自己的 DI 逻辑或插入另一个 DI 框架,例如 Unity、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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
步骤 2 – 在 Global.asax 中设置 WebObjectActivator。
public class Global : System.Web.HttpApplication
{
public override void Init()
{
HttpRuntime.WebObjectActivator = new SimpleActivator();
base.Init();
}
}
Run Code Online (Sandbox Code Playgroud)
第 3 步 – 在您的 Web 表单页面中使用依赖注入。
public partial class WebForm2 : System.Web.UI.Page
{
private ILog _log;
public WebForm2(ILog l)
{
_log = l;
}
}
Run Code Online (Sandbox Code Playgroud)
您可以在此链接中查看此示例以及有关它的更多信息:https ://devblogs.microsoft.com/dotnet/annoucing-the-net-framework-4-7-2/
在我看来,如果您可以迁移到较新版本的 .NetFramework,您应该尝试实现IServiceProvider. 如果你不能,那么你应该分析实施是否PageHandlerFactory会在未来为你节省更多的时间而不是你将花费的时间来实施它。如果它不会在将来为您节省任何时间,您可以继续进行 [Dependency]财产注入。
| 归档时间: |
|
| 查看次数: |
3415 次 |
| 最近记录: |