Asp.net

如何在 ASP.NET Web 窗體中使用依賴注入

  • February 26, 2009

我正在嘗試找出一種將依賴注入與 ASP.NET Web 窗體控制項一起使用的方法。

我有很多控制項可以直接創建儲存庫,並使用它們來訪問和綁定數據等。

我正在尋找一種模式,我可以將儲存庫傳遞給外部控制項(IoC),因此我的控制項仍然不知道儲存庫是如何建構的以及它們來自哪裡等。

我不希望我的控制項依賴於 IoC 容器,因此我只想能夠使用建構子或屬性注入來構造控制項。

(更複雜的是,這些控制項是由 CMS 在執行時建構並放置在頁面上的!)

有什麼想法嗎?

2019 年更新:隨著 Web 表單 4.7.2 的引入,現在可以更好地支持 DI。這使以下內容無效。請參閱:在 .NET 4.7.2 中的 WebForms 中連接 Simple Injector

PageHandlerFactory您可以通過用自定義替換預設值來使用自動建構子注入。這樣,您可以使用重載的建構子來載入依賴項。您的頁面可能如下所示:

public partial class HomePage : System.Web.UI.Page
{
   private readonly IDependency dependency;

   public HomePage(IDependency dependency)
   {
       this.dependency = dependency;
   }

   // Do note this protected ctor. You need it for this to work.
   protected HomePage () { }
}

PageHandlerFactory可以在 web.config 中配置該自定義,如下所示:

<?xml version="1.0"?>
<configuration>
 <system.web>
   <httpHandlers>
     <add verb="*" path="*.aspx"
       type="YourApp.CustomPageHandlerFactory, YourApp"/>
   </httpHandlers>
 </system.web>
</configuration>

CustomPageHandlerFactory可以看起來像這樣:

public class CustomPageHandlerFactory : PageHandlerFactory
{
   private static object GetInstance(Type type)
   {
       // TODO: Get instance using your favorite DI library.
       // for instance using the Common Service Locator:
       return Microsoft.Practices.ServiceLocation
           .ServiceLocator.Current.GetInstance(type);
   }

   public override IHttpHandler GetHandler(HttpContext cxt, 
       string type, string vPath, string path)
   {
       var page = base.GetHandler(cxt, type, vPath, path);

       if (page != null)
       {
           // Magic happens here ;-)
           InjectDependencies(page);
       }

       return page;
   }

   private static void InjectDependencies(object page)
   {
       Type pageType = page.GetType().BaseType;

       var ctor = GetInjectableCtor(pageType);

       if (ctor != null)
       {
           object[] arguments = (
               from parameter in ctor.GetParameters()
               select GetInstance(parameter.ParameterType)
               .ToArray();

           ctor.Invoke(page, arguments);
       }
   }

   private static ConstructorInfo GetInjectableCtor(
       Type type)
   {
       var overloadedPublicConstructors = (
           from constructor in type.GetConstructors()
           where constructor.GetParameters().Length > 0
           select constructor).ToArray();

       if (overloadedPublicConstructors.Length == 0)
       {
           return null;
       }

       if (overloadedPublicConstructors.Length == 1)
       {
           return overloadedPublicConstructors[0];
       }

       throw new Exception(string.Format(
           "The type {0} has multiple public " +
           "ctors and can't be initialized.", type));
   }
}

不利的一面是,這僅在您以完全信任的方式執行時才有效。你可以在這裡閱讀更多關於它的資訊。但請注意,在部分信任的情況下開發 ASP.NET 應用程序似乎是一個失敗的原因

引用自:https://stackoverflow.com/questions/589374