6

I have registered a custom MembershipProvider class in my Web.Config file. I'm using Inversion Of Control using Castle Windsor and I have registered my custom MembershipProvider class as transient (because it's using a service that's transient as well).

This means that I want the Membership provider instance recreated on every web request. Currently, it is created only once per application domain so when it tries to access the service it depends on, that service instance is reused while it is not supposed to.

Now I need to find a way of having Windsor control the lifetime of my custom MembershipProvider but I don't know how. I expected a factory sitting around somewhere in the .NET Framework, allowing me to override the instance creation and rerouting it to Windsor but I can't find anything alike.

By the way, I'm using .NET 4.0.

UPDATE: Here's some of my code so you can see what I'm doing exactly:

Web.Config:

<membership defaultProvider="MyMembershipProvider" >
  <providers>
    <clear/>
    <add name="ApplicationMembershipProvider"
         type="MyNamespace.MyMembershipProvider, MyAssembly"/>
  </providers>
</membership>

Membership Provider

public class MyMembershipProvider : MembershipProvider
{
    private IMyService myService;

    public MyMembershipProvider() : base()
    {
        // We should use constructor injection here but since we cannot control
        // the construction of this class, we're forced to create the dependency
        // ourselves.
    }

    public override bool ValidateUser(string username, string password)
    {
        if (myService == null)
        {
            // This scope is only reached once within the browser session,
            // ASP.NET keeps the instance of MyMembershipProvider in memory
            // so the myService field keeps its value across web requests.
            // This results in Castle Windsor (which I have configured the service
            // locator to use) not being able to control the lifetime of
            // the MyService instance. So, the inability of Windsor to control
            // the lifetime of MembershipProvider instances, inhibits the lifetime
            // management of MyService instances as well.
            myService = ServiceLocator.Current.GetInstance<IMyService>();
        }

        return myService.ValidateUser(username, password);
    }
}
Sandor Drieënhuizen
  • 6,310
  • 5
  • 37
  • 80

2 Answers2

4

I just blogged about this with a solution.

In a nutshell, this solution involves a simple, reusable MembershipProvider that calls the container to resolve your custom MembershipProviders. Unlike other solutions that use "BuildUp" container features, this one takes true control of instantiation, thus enabling constructor injection (which in turn enables immutability) and proxyability.

Mauricio Scheffer
  • 98,863
  • 23
  • 192
  • 275
2

Don't worry about your MembershipProvider lifetime. Simply manage the lifetime of the IMyService within the provider. Create a property for your IMyService with a getter, and return a new instance (or however you want to manage the lifetime) each time it is requested.

Pedro
  • 382
  • 2
  • 7
  • Thanks for your suggestion. My point however, is that I shouldn't be managing object lifetime at all but let Castle Windsor do that instead (Inversion of Control), based on the lifetime configuration I hand over to it. – Sandor Drieënhuizen Nov 16 '10 at 21:35
  • Fine. You can do that. All from within your MembershipProvider class. Just have a property that returns a IMyservice -- and this will simply return whatever is returned from your IoC container. – Pedro Nov 16 '10 at 22:24
  • Yeah but that would cause the service to be created every time the MembershipProvider is called within the same web request. I can live with that to a certain extent but the goal is to let Castle Windsor manage the lifetime and not me. – Sandor Drieënhuizen Nov 17 '10 at 13:33
  • @Sandor: Pedro's solution is correct, you won't get a new instance every time, that's up to the service lifetime as registered in Windsor. Only if the service is a transient would you always get a new instance. In that case you could call the property once and cache the instance for the method call. – Mauricio Scheffer Nov 17 '10 at 23:29