StructureMap:如何将容器发送到具有不接受参数的构造函数的 class

StructureMap: How to send the container to a class that has a Constructor that does not accept Parameters

我正在尝试找出如何将 StructrueMap 容器传递给我编写的继承自另一个 (MS-Class) 的 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 的评论,我将进一步解释 class 的作用。 (希望能解释为什么我的双手被束缚)

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

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

感谢您的帮助

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

it is typical in my experience to have a single container and use that service- or Web-side-wide. In the startup of the service or Web app, you can create the container, register the dependencies, new up an instance of your SecurityTokenServiceConfiguration class, resolve your dependencies, use it to punch out a SecurityTokenService object, and host it.

After the first beta, we really pushed for DI support. We got a little hook in beta 2. You can now create a custom SecurityTokenServiceConfiguration class that overrides the virtual CreateSecurityTokenService method. The implementation in Microsoft's SecurityTokenServiceConfiguration does Activator.CreateInstance; yours can do IoC. This can include the resolution of an IssuerNameRegistiry. Something like this perhaps:

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 class 可以访问它。就个人而言,我不喜欢这个想法,因为它使您的 DI 容器在整个应用程序中都可以访问,这可能导致滥用 DI 容器作为服务定位器。

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