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

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

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

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

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

有什么想法吗?

推荐答案

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相关问答推荐

新的 csproj 文件结构可以与 ASP.NET Framework 项目一起使用吗?

如何在 asp net core api 中使用 Created(或 CreatedAtAction / CreatedAtRoute)

Azure Functions 中的 DI

包含重复的“内容”项目.默认情况下,.NET SDK 包含项目目录中的“内容”项

如何在 ASP.NET Core 中更改 Swagger 的基本 url

使用 Visual Studio 2017 的 .NET Core 解决方案上没有 project.json、global.json ... 等

等价于 ASP.NET Core 中的 Html.RenderAction

ASP.NET Core 中的 NuGet 包位置在哪里?

从非异步代码调用异步方法

使用将 net461 设置为唯一框架的 ASP.NET Core Web 应用程序 (.NET Core) 与使用 (.NET Framework) 模板之间的区别

创建项目 ASP.NET Core (.NET Core) 和 ASP.NET Core (.NET Framework) 有什么区别

错误处理(向客户端发送 ex.Message)

如何设置asp.net身份cookie过期时间

在 ASP.NET Core 1.0 上处理大文件上传

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

“x-powered by”是什么意思?

ASP.NET 5、EF 7 和 SQLite - SQLite 错误 1:“没有这样的表:博客”

找不到路径的一部分... bin\roslyn\csc.exe

解密 Forms cookie 时出现“加密操作期间出错”

System.Web.HttpUtility.UrlEncode/UrlDecode ASP.NET 5 的替换