构造函数注入在 .NET 4.7.2 ASP.NET WebForms 中的依赖注入中不起作用

Ild*_*dar 3 c# asp.net dependency-injection

我使用了文章“在 WebForms 应用程序中使用依赖注入” https://devblogs.microsoft.com/aspnet/use-dependency-injection-in-webforms-application/ \n该项目在项目属性中重新定位到 .NET Framework 4.7.2,并且在 web.config 中:

\n
    <system.web>\n    <httpRuntime targetFramework="4.72" ...\n
Run Code Online (Sandbox Code Playgroud)\n

AspNet.WebFormsDependencyInjection.Unity NuGet 包已安装。
\n类型已在全局中注册:

\n
    public class Global : System.Web.HttpApplication\n    {\n        void Application_Start(object sender, EventArgs e)\n        {\n            var container = this.AddUnity();\n            container.RegisterType<IVCRole, eVCRole>();\n        }\n        ...\n
Run Code Online (Sandbox Code Playgroud)\n

我检查了容器,它正在工作并将接口 IVCRole 映射到类 eVCRole。\nDefault.aspx.cs 已重构:

\n
  public partial class Default : System.Web.UI.Page\n  {\n    private IVCRole vcr; \n    public Default(IVCRole avcr) \n    { \n      vcr = avcr;\n    }   \n    protected void Page_Load(object sender, EventArgs e)\n    {\n    ...\n
Run Code Online (Sandbox Code Playgroud)\n

但是当我运行 Web 应用程序时,出现错误\n“找不到类型 \'ASP.default_aspx\' 的构造函数。”\n如果我添加此构造函数:

\n
  public partial class Default : System.Web.UI.Page\n  {\n    private IVCRole vcr;\n    public Default() {}\n    public Default(IVCRole avcr)\n    { \n      vcr = avcr;\n    }   \n    protected void Page_Load(object sender, EventArgs e)\n    {\n    ...\n
Run Code Online (Sandbox Code Playgroud)\n

DI 的构造函数

\n
    public Default(IVCRole avcr) \n    { \n      vcr = avcr;\n    }\n
Run Code Online (Sandbox Code Playgroud)\n

从未被调用,且 Page_Load 中的“vcr”始终为 null。\n有一篇文章:“ASP.NET Web 表单中的依赖注入”:\n https://makingloops.com/dependency-injection-in-web-forms/ \n提到此错误的地方:\n“有时您可能会看到一个构建错误,抱怨页面上缺少零参数构造函数。我注意到这个错误会根据上下文神奇地消失。其他人建议使用在页面上使用 Dependency 属性进行属性注入来解决此问题,但我\xe2\x80\x99t 发现这是必要的。”\n但就我而言,没有“魔法”。\nStackoverflow 中也有类似的问题:\n .NET 4.7.2 ASP.NET WebForms 网站中的依赖注入 - 构造函数注入不起作用\n但在我的情况下,属性注入不起作用:

\n
public partial class Default : System.Web.UI.Page\n{\n    [Dependency]\n    public IVCRole vcr { get; set; }    \n\n    protected void Page_Load(object sender, EventArgs e)\n    {\n    ...\n
Run Code Online (Sandbox Code Playgroud)\n

Page_Load 中的“vcr”仍然为空。\n有解决方案可以使其与 DI 提供程序的自定义实现一起使用,但我已经使用 .NET 4.7.2 和 Unity。作者提到,对于 Web 应用程序来说应该不会有任何问题,因为问题出在网站编译器上。\n如何使用 .NET 4.7.2 和 Unity 让 DI 构造函数或属性注入在默认页面中工作?

\n

这是堆栈:

\n
[MissingMethodException: Constructor on type \'ASP.default_aspx\' not found.]\n   System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, StackCrawlMark& stackMark) +1173\n   System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes) +130\n   System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture) +21\n   Microsoft.AspNet.WebFormsDependencyInjection.Unity.ContainerServiceProvider.DefaultCreateInstance(Type type) +17\n   Microsoft.AspNet.WebFormsDependencyInjection.Unity.ContainerServiceProvider.GetService(Type serviceType) +161\n   __ASP.FastObjectFactory_app_web_mmaneivx.Create_ASP_default_aspx() in c:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\Temporary ASP.NET Files\\vs\\19e4d468\\8c7800a0\\App_Web_mmaneivx.2.cs:0\n   System.Web.Compilation.BuildResultCompiledType.CreateInstance() +31\n   System.Web.Compilation.BuildManager.CreateInstanceFromVirtualPath(VirtualPath virtualPath, Type requiredBaseType, HttpContext context, Boolean allowCrossApp) +104\n   System.Web.UI.PageHandlerFactory.GetHandlerHelper(HttpContext context, String requestType, VirtualPath virtualPath, String physicalPath) +33\n   System.Web.UI.PageHandlerFactory.GetHandler(HttpContext context, String requestType, String virtualPath, String path) +39\n   System.Web.MaterializeHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +386\n   System.Web.HttpApplication.ExecuteStepImpl(IExecutionStep step) +50\n   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +163\n
Run Code Online (Sandbox Code Playgroud)\n

Dai*_*Dai 5

免责声明:我在 .NET Framework 4.7.2 中维护这个用于ASP.NET WebForms(以及 MVC、SignalR 和 WCF)的NuGet 包 和项目Microsoft.Extensions.DependencyInjection- 但是这篇文章的内容并不特定于我对 ASP 的 DI 实现。网。


  • 检查你的.csproj

    • 确保您的目标是 .NET Framework 4.7.2 或更高版本(请注意,许多共享 Web 主机 - 包括 Azure 应用服务 - 可能运行旧版本的 .NET Framework):

      <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
      
      Run Code Online (Sandbox Code Playgroud)
  • 检查你的web.config

    • 确保您有<system.web><compilation targetFramework="4.7.2">
    • 确保您有<system.web><httpRuntime targetFramework="4.7.2"/>
    • 如果您已<assemblies><clear />确保在<add assembly="*"/> 之后<clear />或以其他方式确保您在<add />元素中明确列出了所有必需的程序集。
  • 您的ConfigureServices方法(或任何配置 DI 的方法)必须在's之前运行!Global.asaxApplication_Start

    • 目前,您的代码正在将 Unity 容器实例化为本地内部容器Application_Start- 这是一个坏主意(因为您没有在字段中保留强引用 - 其他地方的错误可能会导致 GC 收集您的 DI 容器,这将是坏事。

    • 您还需要添加一个IHttpModule来支持范围内的 DI 容器(我的包已经为您做到了这一点)。

    • 这是通过使用PreApplicationStartMethod属性(来自WebActivatorEx.

      • 注意和OWIN的属性PreApplicationStartMethod 不一样[assembly: Microsoft.Owin.OwinStartup()!如果您将 DI 与 SignalR 结合使用,您的项目可能需要同时使用两者。
      • 您的 Startup 类代码应如下所示:
      [assembly: PreApplicationStartMethod ( typeof( global::MyProject.RssStartup ), methodName: nameof( global::MyProject.MyStartup.OnPreStart ) )]
      
      namespace MyProject
      {
          internal static class MyStartup
          {
              internal static void OnPreStart()
              {
                  // Set-up your DI system here and then call your `ConfigureServices` method before this method returns.
              }
          }
      }
      
      Run Code Online (Sandbox Code Playgroud)

  • 戴,谢谢你。就我而言,将“targetFramework”添加到“&lt;httpRuntime&gt;”修复了它。您列出的所有其他标准都已经到位。我现在可以在 WebForms 中使用 ctor 注入。 (2认同)