asp.net-mvcc#-4.0dependency-injectionwifstructuremap4

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


I am trying to find out how I can pass the StructrueMap container to a class that I wrote that inherits from another (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
    }
}

I need portalTenantManager to be the Instance that I have defined in my container in the Global.asax.

My Global Assax has these things setup:

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

Edit: Because of the comments of @NightOwl888 I'll explain a bit further what this class does. (Hopefully explaining so why my hands are tied)

My application is able to authenticate a user with Azure Active Directory and is Multi-tenant capable. In the authentication pipeline I have the possibility to store the validation endpoints in my database instead of the default way on the web.config file. See MSDN and this, which actually is explaining exactly what I'm doing.

So I registered my class in the web.config under the Tag issuerNameRegistry. At some point of the validation pipeline my class is instantiated and the overriden method IsThumbprintValid is beeing called. The problem is that the class registered in issuerNameRegistry expects a parameterless constructor (there it is! the constrained construction!), therefore I cannot create a constructor that would solve my problem.

Thanks for your help


Solution

  • It turns out that this question has been asked before on MSDN, the answer of which was provided by Travis Spencer in 2 different posts.

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

    Of course, this means that you need to create a static instance of your DI container so it is accessible to your SecurityTokenServiceConfiguration class. Personally, I don't like that idea because it makes your DI container accessible throughout the application, which can lead to abuse of the DI container as a service locator.

    Ideally, there would be a way in any DI friendly framework to pass the container into an abstract factory in order to resolve service dependencies. However, since I am not familiar with WIF it is unclear whether that can be done - perhaps the class where the Issue method exists could have a constructor added? The trick is to keep walking up the chain until you find the first place in the framework where you can intervene and do all of your DI configuration there.