我正试图找到一种方法,将依赖项注入与ASP结合使用.NET Web窗体控件.

我有很多控件可以直接创建存储库,并使用它们访问和绑定数据等.

我正在寻找一种模式,在这种模式下,我可以将存储库传递给外部控件(IoC),因此我的控件仍然不知道存储库是如何构造的,以及它们来自何处等.

我不希望依赖我的控件中的IoC容器,因此我只希望能够使用构造函数或属性注入来构造控件.

(更复杂的是,这些控件是由CMS在运行时构造并放置在页面上的!)

有什么 idea 吗?

推荐答案

UPDATE 2019: 随着Web Forms 4.7.2的引入,现在可以更好地支持DI.这将使以下内容无效.请参阅:Wiring up Simple Injector in WebForms in .NET 4.7.2

通过将默认的PageHandlerFactory替换为自定义的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 () { }
}

可以在web.config中按如下方式配置客户PageHandlerFactory:

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

Downside is that this only works when running your side in Full Trust.你可以阅读更多关于它的信息.但是请注意,开发ASP.NET应用程序中的部分信任seems a lost cause.

Asp.net相关问答推荐

在 AppConfig.json 中存储对象的最佳方式

.Net Framework:w3wp.exe 中的异常

检测 ASP.NET 中的内存泄漏

ASP.NET Core 1.0 ConfigurationBuilder().AddJsonFile("appsettings.json");找不到文件

加载特定 UpdatePanel 后如何调用客户端 javascript 函数

用于 ASP.NET 的 System.Drawing 的替代品?

无法让嵌套在 UpdatePanel 中的 WebControl 中的 ScriptManager.RegisterStartupScript 工作

RestSharp 不反序列化 JSON 对象列表,始终为 Null

这两种方法有什么区别?

ASP.NET Core 中的授权. [Authorize] 属性总是 401 Unauthorized

AddDefaultTokenProviders:它是什么以及如何使用那些默认提供者?

如何为角色以及特定用户使用自定义授权属性?

如何在 ASP.NET MVC3 中配置区域

Owin 中是否有来自 Global.asax 的 Application_End?

对 ASP.NET 2.0 网页进行单元测试的最佳方法是什么?

ASP.NET 元:资源键

通过 ASP.NET/C# 使用 Plupload

VS2017 无法加载文件或程序集 Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll 或其依赖项之一

如何使用restsharp下载文件

如何在 ASP.NET 响应中传递大文件?