【问题标题】:StructureMap: How to send the container to a class that has a Constructor that does not accept ParametersStructureMap:如何将容器发送到具有不接受参数的构造函数的类
【发布时间】:2016-01-01 20:55:31
【问题描述】:

我正在尝试找出如何将 StructrueMap 容器传递给我编写的从另一个(MS-Class)继承的类。

namespace TheNamespace
{
  public class DatabaseIssuerNameRegistry : ValidatingIssuerNameRegistry
  {
    /* **This can't be done**
    public DatabaseIssuerNameRegistry(IPortalTenantManager portalTenantManager)
    {
        _someField= portalTenantManager;
    }*/


    protected override bool IsThumbprintValid(string thumbprint, string issuer)
    {
       //How does it work ???????????

       var portalTenantManager = container.GetInstance<IPortalTenantManager>();
      //Do something with the portalTenantManager
    }
}

我需要 portalTenantManager 作为我在 Global.asax 的容器中定义的实例。

我的 Global Assax 设置了这些东西:

protected void Application_Start()
{
 var container = new Container();
 container.Configure(x =>
            { ....
              ....
             x.For<IPortalTenantManager>().Use<PortalTenantManager>();
             });

...

...
ControllerBuilder.Current.SetControllerFactory(new StructureMapControllerFactory(container));
...
GlobalConfiguration.Configuration.DependencyResolver = new StructureMapApiControllerFactory(container);
...
    }

编辑: 由于@NightOwl888 的cmets,我将进一步解释这个类的作用。 (希望能解释一下为什么我的手被绑住了)

我的应用程序能够使用 Azure Active Directory 对用户进行身份验证,并且支持多租户。在身份验证管道中,我可以将验证端点存储在我的数据库中,而不是 web.config 文件中的默认方式。 See MSDNthis,这实际上是在解释我在做什么。

所以我在标签 issuerNameRegistry 下的 web.config 中注册了我的课程。在验证管道的某个时刻,我的类被实例化,并且被覆盖的方法 IsThumbprintValid 正在被调用。问题是在 issuerNameRegistry 中注册的类需要一个无参数构造函数(就是它!受约束的构造!),因此我无法创建一个可以解决我的问题的构造函数。

感谢您的帮助

【问题讨论】:

  • 如果您解释为什么无法添加构造函数会很有帮助,因为这似乎是解决问题最明显的方法。
  • 我现在不这样做,只是不会让我这样做。在使用 Azure-AD 进行身份验证期间,此类在 IIS 管道中的某处被调用。如果我创建构造函数 public DatabaseIssuerNameRegistry(IPortalTenantManager portalTenantManager).. 它失败
  • 您期望您的新类将如何被框架使用?你为什么没有发布框架文档的链接?您需要明确您的类是如何实例化的,并且不是使用constrained construction 完成的。
  • 感谢@NightOwl88 的评论。我已经按照您的建议对问题进行了一些编辑,包括一些链接,并阅读了有关受限结构的链接,但就是这样!

标签: asp.net-mvc c#-4.0 dependency-injection wif structuremap4


【解决方案1】:

原来这个问题有been asked before on MSDN,Travis Spencer 在 2 个不同的帖子中提供了答案。

根据我的经验,典型的做法是拥有一个容器并在整个服务或 Web 端使用该容器。在服务或 Web 应用启动时,您可以创建容器、注册依赖项、新建 SecurityTokenServiceConfiguration 类的实例、解析依赖项、使用它来打出 SecurityTokenService 对象并托管它。

在第一个测试版之后,我们真正推动了 DI 支持。我们在 beta 2 中有一个小钩子。您现在可以创建一个自定义 SecurityTokenServiceConfiguration 类来覆盖虚拟 CreateSecurityTokenService 方法。 Microsoft 的 SecurityTokenServiceConfiguration 中的实现是 Activator.CreateInstance;你的可以做 IoC。这可以包括对 IssuerNameRegistiry 的解析。可能是这样的:

RequestSecurityTokenResponse Issue(IClaimsPrincipal principal, RequestSecurityToken request)
{
    SecurityTokenServiceConfiguration config = new MyGoodSecurityTokenServiceConfiguration();
    SecurityTokenService sts = config.CreateSecurityTokenService();
    RequestSecurityTokenResponse rstr = sts.Issue(principal, request);

    return rstr;
}

public class MyGoodSecurityTokenServiceConfiguration : SecurityTokenServiceConfiguration
{
    public override SecurityTokenService CreateSecurityTokenService()
    {
        IssuerNameRegistry = IoC.Resolve<IssuerNameRegistry>();
    
        var sts = IoC.Reslove<SecurityTokenService>();

        return sts;
    }
}

当然,这意味着您需要创建 DI 容器的静态实例,以便您的 SecurityTokenServiceConfiguration 类可以访问它。就我个人而言,我不喜欢这个想法,因为它使您的 DI 容器在整个应用程序中都可访问,这可能导致将 DI 容器用作服务定位器的滥用。

理想情况下,有一种方法in any DI friendly framework 将容器传递到抽象工厂以解决服务依赖关系。但是,由于我对 WIF 不熟悉,因此尚不清楚是否可以这样做 - 也许 Issue 方法所在的类可以添加一个构造函数?诀窍是不断向上走,直到找到框架中的第一个位置,您可以在那里进行干预并在那里进行所有 DI 配置。

【讨论】:

  • 感谢您的回复,我遇到的“问题”,我正在尝试摆脱我的 DI 容器的静态实例……好吧,我无法添加构造函数,我必须为我的容器创建一个新实例。代码有异味.. 但我暂时先离开它。
  • 我想一个可能的替代解决方案是创建一个抽象工厂,该工厂设置在一个静态方法中,您的 WIF 类可以访问该方法来解析 IssuerNameRegistrySecurityTokenService。然后将你的容器注入到工厂的实现中。至少这样你就不会将容器暴露给应用程序的其余部分以作为服务定位器滥用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-25
  • 1970-01-01
  • 2018-02-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多