Our entities all have modified and created dates associated with them and we wanted these set automatically. I settled on using an interceptor which is discussed by Ray Houston here and a caveat (Actually just some fine print I would have missed) discussed here by Jan Van Ryswyck.

All you do is create a class that inherits from NHibernate.EmptyInterceptor (Which itself implements IInterceptor and allows you to only handle the things you want to handle) and override the the methods you want to handle. In our case we just needed inserts (OnSave) and updates (OnFlushDirty). Return true on those methods only if you made a modification otherwise return false. I created and interface that identifies an entity:

public interface IEntity
{
    Guid Id { get; }
    DateTime Modified { get; set; }
    DateTime Created { get; set; }
}

... and we only operate on entities that implement this interface:

public class EntityInterceptor : EmptyInterceptor
{
    public override bool OnSave(object entity, object id, object[] state, 
        string[] propertyNames, NHibernate.Type.IType[] types)
    {
        if (!(entity is IEntity)) return false;

        var created = DateTime.Now;
        SetState<IEntity>(propertyNames, state, x => x.Created, created);
        SetState<IEntity>(propertyNames, state, x => x.Modified, created);
        return true;
    }

    public override bool OnFlushDirty(object entity, object id, object[] currentState,
         object[] previousState, string[] propertyNames, NHibernate.Type.IType[] types)
    {
        if (!(entity is IEntity)) return false;

        SetState<IEntity>(propertyNames, currentState, x => x.Modified, DateTime.Now);
        return true;
    }

    private void SetState(string[] propertyNames, object[] state, 
        Expression<Funcobject>> property, object value)
    {
        var index = Array.IndexOf(propertyNames, property.GetPropertyName());
        if (index == -1) return;
        state[index] = value;
    }
}

The key is to set the state in OnSave and the currentState in OnFlushDirty to the new value, do not modify the entity. The names of the values are held in the propertyNames array, thus the need for the SetState method to lookup the index of the property you want to modify. One thing I didn't like about my first incarnation were the magic strings for the property names. So I shamelessly ripped off some code from Gabriel Schenkers post on Dynamic vs Static Reflection (A really good read!) to allow me to pass an expression instead of a magic string. I turned it into extension methods as follows:

public static class ExpressionExtensions
{
    public static string GetPropertyName(this Expression<Funcobject>> expression)
    {
        var memberExpression = expression.GetMemberExpression();
        var propertyInfo = memberExpression.Member as PropertyInfo;
        return propertyInfo == null ? null : propertyInfo.Name;
    }

    public static MemberExpression GetMemberExpression(
                      this Expression<Funcobject>> expression)
    {
        MemberExpression memberExpression = null;
        if (expression.Body.NodeType == ExpressionType.Convert)
        {
            var body = (UnaryExpression)expression.Body;
            memberExpression = body.Operand as MemberExpression;
        }
        else if (expression.Body.NodeType == ExpressionType.MemberAccess)
        {
            memberExpression = expression.Body as MemberExpression;
        }
        if (memberExpression == null)
        {
            throw new ArgumentException("Not a member access", "member");
        }
        return memberExpression;
    }
}

Fluently registering the interceptor is as follows:

_sessionFactory =
    Fluently.Configure().
        Database(persistenceConfigurer).
        Mappings(m => m.FluentMappings.AddFromAssembly(Assembly.GetExecutingAssembly())).
        ExposeConfiguration(config => config.Interceptor = new EntityInterceptor()).
        BuildSessionFactory();