bling.github.io

This blog has relocated to bling.github.io.
Showing posts with label IoC. Show all posts
Showing posts with label IoC. Show all posts

Monday, October 31, 2011

My Thoughts on MEF

Ever since MEF was conceived, despite the authors saying that it is not an IoC container, it has since evolved to become one of the more popular IoC containers.  I’ve always avoided it because I disagree with using attributes, and I’ve had no reason to use it over Autofac or Windsor.

Recently, I found a reason to use it – Metro-style applications only support MEF so far.  My Twitter client ping.pong uses Autofac as the IoC container.  It uses some very basic functionality like factories and hooks.  To my surprise, MEF has no support for either of these.

Coming across these limitations solidifies my opinion that MEF is a plugin container, not an IoC container.

First let’s take a look at automated factories. What I mean is that by registering Foo, like so:

container.RegisterType<Foo>();

the container will automatically provide us a Func<Foo> without explicitly having to register it. This can be useful when you want to create an instance of Foo some time in the future rather than at constructor time.  You can do this with MEF via an ExportFactory<T>, but it’s limited because you cannot override dependencies at resolve time.

For example, let’s say Foo has a constructor of Foo(Bar1, Bar2, Bar3). With MEF, you have no control at resolution time what the Bars are. A container that has support for automated factories (like Autofac and Castle Windsor), will let you resolve a Func<Bar1, Foo>, which lets you override Bar1 at resolve time. Similarly, you can resolve a Func<Bar1, Bar2, Bar3, Foo> and override all dependencies. Any dependencies not overridden fall back to their configuration in the bootstrapper. This is a very useful feature, and coupled with the scoping features for automatic disposal it opens up many doors for elegant solutions for what otherwise are complicated problems.

On to the second point; MEF has limited extension points. This one sounds odd since MEF is all about designing decoupled plugins so surely it should have extension points! The problem here is that MEF is designed as an explicit API (attributes are required) rather than an implicit API. In Autofac, you can scan an assembly and register every type. In MEF, every class needs to have an [Export] on it.  It also baffles my mind why [ImportingConstructor] is required even when there’s only one constructor. All this explicitness means you lose a bunch of “free” extension points that typical IoC containers have, like this:

b.RegisterAssemblyTypes(GetType().Assembly)
  .OnActivated(x => x.Context.Resolve<IEventAggregator>().Subscribe(x.Instance));

What the code above is saying that every time any component is activated, it will subscribe to the event aggregator. If the component doesn’t IHandle<> any messages, it’s a no-op and continues on. If the instance does IHandle<> messages, this will ensure it’s hooked up.

The closest thing I could find in MEF was IPartImportsSatisfiedNotification (yes, an interface, more explicitness!).  It contains a single method OnImportsSatisfied() which gets called when the part is created.  Needless to say, the one line of code from Autofac would translate into a method for every implementation of IHandle<>, and since OnImportsSatisfied() contains no contextual information, every component will need IEventAggregator injected just to be able to call Subscribe.

To fully complete this example, Autofac has the following methods when registering a component: OnRegistered, OnPreparing, OnActivating, OnActivated, and OnRelease.  Each of these methods gives you complete contextual information at the time it is called like access to the current scope of the container, the instance (if applicable), which component which requested the dependency, etc.  This makes it almost too easy to extend the container.

For MEF, the only real extension point is an ExportProvider.  It is pretty low level (all it does is parse attributes for you) so to write anything similar for MEF requires a lot more code.  To further illustrate this point, compare the interception modules from AutofacContrib and MefContrib.  The Autofac implementation is a single file with a couple extension methods.  The MEF implementation is an entire namespace, over multiple classes, not the mention that it also relies on other infrastructure code in MefContrib.  Basically, the guys that wrote MefContrib had to write a mini-container within MEF.

MEF is great for building extremely loosely coupled applications.  I don’t think it has any business in an application where you know and own all of the dependencies; there are simply better libraries for that.

Friday, May 14, 2010

Contextual Lifestyle with Castle Windsor

EDIT: As of version 3, scoped lifestyles are now a first class citizen supported out of the box (http://docs.castleproject.org/Windsor.Whats-New-In-Windsor-3.ashx)
EDIT: A much better implementation can be found at https://github.com/castleprojectcontrib/Castle.Windsor.Lifestyles

IMO, one of the big missing features of Castle Windsor is that it doesn’t come with a built-in way for dealing with contextual lifestyles.  It handles transients and singletons fairly well, but once you get to other lifestyles it’s pretty heavily dependent on having some “state manager” handling the instances.  For example, PerWebRequest uses the HttpContext, PerThread uses thread static variables, etc.
Contextual lifestyles is one of those things where it doesn’t seem all that useful at first, and then when you see the possibilities it’s like getting hit with a huge truck.
A question was posted to the Castle Google Group recently, which I follow, which illustrates a relatively common example of why someone would want to have a contextual lifestyle.  Basically, you have a whole bunch of components you want to resolve, but only within a context.
Here’s some boiler plate code of the domain model:
public interface IRepository { ISession Session { get; } }
public interface ISession : IDisposable { bool IsDisposed { get; } }
public class Session : ISession
{
    public bool IsDisposed { get; set; }
    public void Dispose() { IsDisposed = true; }
}
public class Repository1 :IRepository
{
    public ISession Session { get; private set; }
    public Repository1(ISession session){ Session = session; }
}
public class Repository2 : IRepository
{
    public ISession Session { get; private set; }
    public Repository2(ISession session){ Session = session; }
}
public class Model1
{
    public IRepository First { get; private set; }
    public IRepository Second { get; private set; }
    public Model1(IRepository first, IRepository second) { First = first; Second = second; }
}
public class Model2
{
    public IRepository Second { get; private set; }
    public Model2(IRepository second) { Second = second; }
}
And here’s the unit test I want to pass:
[Test]
        public void ResolutionsByContext()
        {
            IWindsorContainer root = new WindsorContainer();
            root.Register(Component.For<Model1>().LifeStyle.Transient,
                          Component.For<Model2>().LifeStyle.Transient,
                          Component.For<IRepository>().ImplementedBy<Repository1>().LifeStyle.Transient,
                          Component.For<IRepository>().ImplementedBy<Repository2>().LifeStyle.Transient,
                          Component.For<ISession>().ImplementedBy<Session>().LifeStyle.PerContextScope());

            Model1 model1;
            Model2 model2;
            ISession session1, session2;
            using (var context1 = root.BeginLifetimeScope())
            {
                model1 = context1.Resolve<Model1>();
                session1 = model1.First.Session;
                Assert.AreSame(model1.First.Session, model1.Second.Session);
                Assert.AreSame(context1.Resolve<ISession>(), context1.Resolve<ISession>());

                using (var context2 = root.BeginLifetimeScope())
                {
                    model2 = context2.Resolve<Model2>();
                    session2 = model2.Second.Session;
                    Assert.AreNotSame(model1.First.Session, model2.Second.Session);

                    var anotherModel2 = context2.Resolve<Model2>();
                    Assert.AreSame(anotherModel2.Second.Session, model2.Second.Session);

                    Assert.AreSame(session2, context2.Resolve<ISession>());
                    Assert.AreNotSame(context1.Resolve<ISession>(), context2.Resolve<ISession>());
                }
                Assert.IsTrue(session2.IsDisposed);
                Assert.IsFalse(session1.IsDisposed);
            }
            Assert.IsTrue(session1.IsDisposed);
        }

I copied the name BeginLifetimeScope from Autofac, which inherently supports contextual scopes as a first-class citizen (of which the test passes).  The question now, is how do we get Castle Windsor to do the same?
Initially, I took a look at ISubDependencyResolver and caching variables.  Unfortunately, this didn’t work too well because sub resolvers never got hit if they were resolved from the container directly.
The next step I tried was with lifestyle managers, but alas, the CreationContext was always transient and I was unable to store any state that distinguished between different context resolutions.
After digging deeper into the Windsor codebase and getting into the subsystems and handlers, I found a solution that seems to work.  It passes the test above, but that’s about it.  Test well if you’re gonna use this in production code!!!
Here goes!
First, you have a lifestyle manager to distinguish between other lifestyles.
public class ContextualLifestyleManager : AbstractLifestyleManager
    {
        private object instance;
        public override object Resolve(CreationContext context)
        {
            return instance ?? (instance = base.Resolve(context));
        }
        public override void Dispose()
        {
        }
    }
And finally, the magic happens with this:
public static class ContextualExtensions
    {
        public static ComponentRegistration<T> PerContextScope<T>(this LifestyleGroup<T> group)
        {
            return group.Custom<ContextualLifestyleManager>();
        }
        public static IWindsorContainer BeginLifetimeScope(this IWindsorContainer parent)
        {
            var child = new WindsorContainer();
            var ss = (INamingSubSystem)parent.Kernel.GetSubSystem(SubSystemConstants.NamingKey);
            foreach (var handler in ss.GetHandlers())
            {
                if (handler.ComponentModel.CustomLifestyle == typeof(ContextualLifestyleManager))
                {
                    child.Kernel.AddCustomComponent(handler.ComponentModel);
                }
            }
            parent.AddChildContainer(child);
            return child;
        }
    }
First method is just a helper method to be a little more fluent in the registration for when you want many things to have contextual lifestyle.  The second method is the guts.  Long story short, we create a child container, and duplicate all component models of contextual lifestyle.  Thus, whenever components are resolved, the “override” is found in the child and resolved.  Anything else will be found in the parent.
I was initially pretty happy with this, until I profiled the performance.  With Autofac, creating and disposing 100,000 contexts took 5ms on my computer.  Doing the same with with Windsor took 3.8 seconds.  Out of curiosity, I profiled again, but this time just creating child containers without copying handlers down: 1.9 seconds.  So while this implementation works, it’s not as performant as I’d like it to be….
Maybe I’ll come up with another solution, but for now if the performance is acceptable maybe this would be useful for others!

Wednesday, April 21, 2010

Forcing Castle Windsor to Generate Class Proxies

I don't know why it took me so long to come up with this idea, but to save others potential headaches...have you ever thought "hmmmm, I registered this as an interface with an implementation, but I want Windsor to use a class proxy, not an interface proxy, how do I do that?"

For me, initially I almost went as far as implementing my own ProxyFactory to force it to use class proxy no matter what, and then the light bulb hit me and it turns out that there's a much easier way to accomplish this.

c.Register(Component.For<ConcreteImpl, IService>().Interceptors<AnInterceptor>());

Tada!  The actual service is now a concrete type, so Windsor will go, OK, I need to create a class proxy.  But since it's forwarded to the interface as well, all your dependencies can simply use the interface and everything magically works.

Yay!

Monday, April 5, 2010

Windsor/DynamicProxy/Mixin Powers!

Hmmm, I couldn’t really think of a good title except that this blog post has a little bit of everything of the title.

As with any multithreaded program, deadlocks are a huge pain in the butt, and when they happen it costs time, money, and stress.

In my code base I’ve introduced something called an ExtendedLock, which basically has something like this inside:
   1:  public class ExtendedLock : IExtendedLock {
   2:    public IDisposable Lock() {
   3:      while (!Monitor.TryEnter(this, 5000)) {
   4:        IncrementLockTime();
   5:      }
   6:      return new Disposer(() => Release());
   7:    }
   8:    public event Deadlock;
9: }


Pretty simple.  IncrementLockTime, as the name implies keeps track of how long the current thread has been attempting to acquire the lock.  It returns a Disposer which takes an Action, which releases the lock.  This allows us to take advantage of the using syntax, and avoid boiler plate try/finally (oh, and it avoids typos in Monitor.Exit).  After some configurable amount of time, if the lock cannot be acquired within, say, 2 minutes, it’s probably a good probability your application is blocked somewhere.

Now, using this class basically means replacing lock(_syncRoot) type code with _elock.Lock().  Also, I believe it’s a good candidate for “mixing” into any other component.  Mixins are sort of like multiple-inheritance, but not.  I like to think of mixins as a “can do” rather than “is a.”

Now, we know that C# doesn’t let you do multiple inheritance, but with libraries like Castle’s DynamicProxy2, it lets you do something very similar, and is extremely powerful.  In a sense, it will automatically generate the following code for you:


   1:  public class SomeService : ISomeService, IExtendedLock {
   2:    IExtendedLock _lock = new ExtendedLock();
   3:    public void DoSomething() { }
   4:    IDisposable IExtendedLock.Lock() { return _lock.Lock(); }
   5:  }



_lock is a private instance variable, SomeService implements IExtendedLock, and simply redirects all the interface methods to _lock.  This seems pretty simple and straightforward, but becomes tedious when the type you want to mix in has many methods (as my actual IExtendedLock is).

With Windsor/DynamicProxy, you can do this automatically with minimal amount of code.  For example, first you define something like this:

public interface ILockableDictionary : IDictionary, IExtendedLock { }

Then, you register it in the container:

   1:  var container = new WindsorContainer();
   2:  container.Register(Component.For(typeof(ILockableHashtable))
   3:                                     .LifeStyle.Transient
   4:                                     .Activator<LockableHashtableActivator>());


Now, whenever you need an instance of a lockable hashtable you can simply do something like this:

var hash = container.Resolve<ILockableHashtable>();
using (hash.Lock()) {
hash["1"] = 1;
}


You might be wondering why it’s worth all this trouble, and what’s wrong with regular locks and Monitor.  For our system it’s pretty critical that it stays running 24/7, and every minute it’s down is money lost, so it is in our best interest to detect any problematic condition.

Last but not least, here’s the important code that actually generates the proxy:

   1:  internal class LockableHashtableActivator : DefaultComponentActivator
   2:  {
   3:      public LockableHashtableActivator(ComponentModel model, IKernel kernel, ComponentInstanceDelegate onCreation, ComponentInstanceDelegate onDestruction)
   4:          : base(model, kernel, onCreation, onDestruction)
   5:      {
   6:      }
   7:   
   8:      public override object Create(CreationContext context)
   9:      {
  10:          IExtendedLock lockMixin = Kernel.Resolve<IExtendedLock>();
  11:   
  12:          // an additional object we want to "mix" with the implementation to provide combined functionality
  13:          ProxyGenerationOptions options = new ProxyGenerationOptions();
  14:          options.AddMixinInstance(lockMixin);
  15:          
  16:          return Kernel.Resolve<ProxyGenerator>().CreateInterfaceProxyWithTarget(
  17:              typeof(IDictionary), // the interface of the implementation
  18:              new[] { typeof(ILockableHashtable) }, // additional interfaces to use
  19:              Activator.CreateInstance<Hashtable>(), // concrete implementation to mix into
  20:              options);
  21:      }
  22:  }


For those who are familiar with Windsor and wondering why I didn’t use the fluent Proxy.Mixins method, it’s because those mixins are created once per registration.  In this case, it is very important that each mixin (which is an extended lock), is transient, otherwise every lockable hashtable ends up with the same extended lock, which is just asking for trouble.

Saturday, September 26, 2009

Autofac’s extremely powerful and flexible ContainerScope

I need to show some love and support for my favorite IoC tool because it’s most powerful feature needs more explaining.  It’s not that the main site doesn’t provide a good explanation, because it does, but because most people don’t really understand what the solution is solving.
The following is on Autofac’s front page:
var container = // ...
using (var inner = container.CreateInnerContainer())
{
  var controller = inner.Resolve<IController>();
  controller.Execute(); // use controller..
}
The first time I saw this I basically glanced right passed it.  Honestly I didn’t think anything of it, and initially the reason I tried out Autofac was for its very slick lambda registrations.  I didn’t realize I was in a world of surprises when I finally realized the power and flexibility of Autofac’s container scope.

If benchmarks and feature comparisons are not enough show off Autofac’s features, this blog post hopes to show how to solve “complex” problems elegantly.

Let’s start with the typical NHibernate use-case.  Create 1 singleton, create many sessions-per-request.  Here’s a solution with Ninject (not that I’m picking on Ninject, because I love its very slick contextual binding, but because most other IoC containers have a similar solution, like per-session with WCF & Windsor).

Basically, the solutions mentioned above will following an approach like this:

a) Hook into the beginning of a request, and create the ISession from the ISessionFactory.
b) Set it in the HttpContext.Current or OperationContext.Current’s dictionaries.
c) Get this property in all the dependencies that need it.
d) At the end of the request, Dispose() the ISession.

OK, pretty simple and straightforward solution, but there’s one key thing that really bugs me is that by doing this we have introduced a dependency…that is, HttpContext.Current[].  That, or you could wrap that around a class, like SessionManager, again, basically coupling to a dependency under a different name.  With Autofac, we can bypass steps b and c entirely and only worry about the beginning and end of a request.

To start off, here's the basic wiring needed:
1:   var cb = new ContainerBuilder(); 
2:   cb.Register(x => CreateSessionFactory())
       .As<ISessionFactory>()
       .SingletonScoped(); 
3:   cb.Register(x => x.Resolve<ISessionFactory>().OpenSession())
       .As<ISession>()
       .ContainerScoped(); 
4:   IContainer c = cb.Build(); 
5:   
6:   Assert.AreSame(c.Resolve<ISessionFactory>(), c.Resolve<ISessionFactory>()); 
7:   Assert.AreSame(c.Resolve<ISession>(), c.Resolve<ISession>()); 
8:   
9:   var inner1 = c.CreateInnerContainer(); 
10:  Assert.AreSame(c.Resolve<ISessionFactory>(), inner1.Resolve<ISessionFactory>()); 
11:  Assert.AreNotSame(c.Resolve<ISession>(), inner1.Resolve<ISession>());
That’s the configuration.  And that’s it!  Nothing more.  No additional SessionManager class.  No need to use HttpContext.Current to store the session.  Just pass ISession in with regular constructor/property injection.

Here’s how it works:

Line 2: ISessionFactory is created from CreateSessionFactory().  This is a singleton so there will always be one and only one instance of it within the container (and all child containers).

Line 3: This is where it’s interesting.  We’re saying “whenever I need an ISession, resolve ISessionFactory and call OpenSession() on it”.  Also, by specifying ContainerScope, we only get 1 instance per-container.

And this is where it’s sort of confusing with the terminology.  You can think of Autofac as a tree of containers.  The root container (variable c in this case), can create children containers (inner1 in this case, and inner1 could create an inner2, and so on).  So when something is Singleton scoped, that means that the root container, and any child containers (and child’s children) will only have 1 instance of a service.  With ContainerScope, each “node = container” in the tree gets 1 instance.

So back to the unit test above, in line 6 we verify that there is only 1 instance of ISessionFactory.  We resolve ISession twice as well, which shows that we get the same instance.

Line 9, we create an inner container, and here we see that ISessionFactory is the same for both the container c and inner container inner1.  However, the ISession resolved is different between the two.
Thus, by specifying ContainerScope, you can very easily group multiple services and dependencies together as one unit.  Implementing the Unit of Work pattern is insanely easy with Autofac.  Create services A, which depends on B, which depends on C, which all the previous depends on D.  Resolve A within a new inner container, and B, C, and D will always be the same instances.  Resolve A in another inner container and you will get a new set of instances.

Last but not least, Autofac will automatically call Dispose() on all resolved services once the container is disposed.  So for the above, once inner1.Dispose() is called, ISession.Dispose() is automatically called.  If you needed to, you can very easily hook into this mechanism and implement things like transactions and rollbacks.

I hope this blog post clears things up a little bit about Autofac’s ContainerScope!

Monday, September 7, 2009

Member injection module for Autofac

Inevitably as a project gets more complicated, you will need to start using more features of your IoC container. Autofac has built-in support for property injection by hooking into the OnActivating or OnActivated events, which basically set all public properties (or only those which are unset). However, I didn't really like this because once you start using properties, it's not as clear cut as constructors that you are using injection. It becomes hard to manage later on when you have many properties which some should be injected and others should be manually set in code. Autofac's inject all or only-null approach doesn't fit the bill when a class gets a little more complicated. I set up to fix this by writing a custom module, and it turned out to be very very simple. With attributes, we can mimic functionality that's used in Ninject. Here's the module code:
public class MemberInjectionModule : IModule
{
  public void Configure(IContainer container)
  {
    container.ComponentRegistered += (oo, ee) =>
      ee.ComponentRegistration.Activated += (o, e) =>
    {
      const BindingFlags flags = BindingFlags.Instance |
                                 BindingFlags.NonPublic |
                                 BindingFlags.Public;
      var type = e.Instance.GetType();
      foreach (var field in type.GetFields(flags))
      {
        if (field.GetCustomAttributes(typeof(InjectedAttribute), true).Length > 0)
          field.SetValue(e.Instance, e.Context.Resolve(field.FieldType));
      }
      foreach (var prop in type.GetProperties(flags))
      {
        if (prop.GetCustomAttributes(typeof(InjectedAttribute), true).Length > 0)
        {
          if (prop.GetIndexParameters().Length > 0)
            throw new InvalidOperationException("Indexed properties cannot be injected.");

          prop.SetValue(e.Instance, e.Context.Resolve(prop.PropertyType), null);
        }
      }
    };
  }
}
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class InjectedAttribute : Attribute { }
And that's it! Pretty basic reflection here stuff here, but as you can see...iterate through all fields and properties (including privates), and try to resolve them. Now, you can just RegisterModule(new MemberInjectionModule()), and inside your services you simply annotate your properties/fields with the [Injected] attribute, like so:
public class SomeService : ISomeService
{
  [Injected]
  protected ISomeOtherService SomeOtherService { get; set; }
}
And now, it's a very clear cut way of explicitly defining which properties (and fields) should be injected. Also, it's also a simple string property away defined in the attribute if you want to specify a named service, which I'll leave the the reader to implement :)

Friday, August 21, 2009

Session management with NHibernate and Autofac: Corollary

Ooops, I forgot to mention that it's easily mockable as well.
public class UserService : IUserService {
  public UserService(ISessionFactory factory, UsersRepositoryFactory usersFactory) { ... }
}
So that's the basic thing right. So now, with Moq, we can do this:
var mockUserRepo = new Mock<IUsersRepository>();
mockUserRepo.Setup(x => x.GetUser(It.IsAny<string>())).Returns(() => someUser);

var userService = new UserService(..., x => mockUserRepo.Object);
So what I've basically done is insert a lambda expression into the constructor, which is the delegate, which always returns my mock repository. Pretty nifty methinks!

Thursday, August 20, 2009

Session management with NHibernate and Autofac

NHibernate is a beast let me tell you! I think I already mentioned this in the previous post, but NHibernate definitely has a VERY high learning curve. If it wasn't for FluentNHibernate I'd probably still be struggling with XML mapping files right now.

But anywho, it didn't take long for me to run into very many problems with NHibernate. It's not really NHibernate's fault, but more of maybe I'm trying to use the wrong tool for the job.

I'm using DDD for my project, and there's a clear separation between the client and the domain. I got lazy and I didn't make any DTOs for my entities, and just used the [DataContract] and [DataMember] to have WCF automatically generated "DTO"s for me (and in the options turn OFF reusing assemblies).

(Disclaimer: I am *not* by any means knowledgeable about NHibernate, but maybe, just maybe what I say here might point other people in the right direction)

OK, all is good. I can store my entities in the database, I can read them back. So I fire up my client and read some users, and it blows up. NHibernate by default lazy loads everything. Here's what I originally had in my UsersRepository
public IEnumerable<User> GetAll() {
using (var session = _factory.OpenSession())
return session.CreateCriteria<User>().List<User>();
}

It looks pretty innocent. But it blows up. Why? If Users has a collection of other entities (which mine did), they are not loaded with the above code. They are loaded on-demand, i.e. lazy loaded. So when my WCF service finally returns the objects and serializes them, it pukes and throws an exception because the session was long closed already.

Easy solution was to Not.LazyLoad() all my collections. Now here's what I'm thinking I might not be using the right tool for the job because I am purposely disabling one of the key features of NHibernate. By default, caching is always enabled, and I couldn't find anywhere how to globally turn it off. You must go class by class.

OK, so on to my next problem. I soon ran into issues with entities not being unique. I would have code like this in my UserService:
public void AddProduct(string username, Guid productId) {
var user = _usersRepository.GetUser(username);
var product = _productRepository.GetProduct(productId);
user.Products.Add(product);
_usersRepository.Store(user);
}

Again, this puked. The problem here was after my GetUser call, inside my repository, like my first example, I had a using(session), which closed when the method ended. Shortly after, I am trying to update the same user, but with a *different* session. NHibernate doesn't like this, an NHibernate.NonUniqueObjectException is thrown, and I had a new problem to deal with.

It became clear I had to actively manage the sessions somehow, and the best place would be to have them in my services, which typically each method had a "unit of work" placed on them.

So the goal I wanted to accomplish was to initiate a new session at the beginning of a service method, call a repository multiple times, close the session, and then exit the method.

So how can we achieve that?

I thought of a couple things, and the first thing I did actually was to use AOP style and use Autofac with Castle.DynamicProxy. I created an interceptor for my service, and before invocation I opened a session, then manually called a property setter for a CurrentSession, and after invocation close the session.

It did the job, but had some problems:
a) It did a little too much black magic for me. All methods got intercepted.
b) I still had to manually set the CurrentSession property of my repositories. Sooner or later I'm sure to run in the threading problems.

After I got that half working I scrapped it and tried to come up with something better. This is what I came up with:
public delegate IUsersRepository UsersRepositoryFactory(ISession session);

public class UserService : IUserService {
public UserService(ISessionFactory factory, UsersRepositoryFactory usersFactory) { ... }
}

public class UsersRepository : IUsersRepository {
public UsersRepository(ISession session) { ... }
}

Now, when I call a method on my UserService, I do this:
public void AddProduct(string username, Guid productId) {
using (var session = _factory.OpenSession()) {
var userRepo = _userRepoFactory(session);
var productRepo = _productFactory(session);
...
}
}

And, of course, the Autofac code:
b.Register<UsersRepository>().As<IUsersRepository>().FactoryScoped();
b.RegisterGeneratedFactory<UsersRepositoryFactory>();

More details on the delegate factory here. But basically, with Autofac I have told it to inject delegates into my UserService, and those delegates can create new instances of my user repository by passing in the current session.

You'll also notice I had a products repository as well. With these delegate factories I can create up multiple repositories on the fly with the same session (and all the good NHibernate stuff that comes with that).

Sure, there's a whole bunch of using(var session) boilerplate now, but it's explicit, clear, and allows for a lot of fine-grained control.

EDIT: I have since dropped this approach and I'm currently injecting ISessions into my constructors by using Autofac's container-scope (something that took me a while to understand).