Skip to content

Instantly share code, notes, and snippets.

@mikeobrien
Last active February 18, 2020 10:06
Show Gist options
  • Save mikeobrien/cad8e66456d45ff0a5e2 to your computer and use it in GitHub Desktop.
Save mikeobrien/cad8e66456d45ff0a5e2 to your computer and use it in GitHub Desktop.
NHibernate Composite Interceptor
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using MoreLinq;
using NHibernate;
using NHibernate.SqlCommand;
using NHibernate.Type;
public class CompositeInterceptor : IInterceptor
{
private readonly IEnumerable<IInterceptor> _interceptors;
public CompositeInterceptor(IEnumerable<IInterceptor> interceptors)
{
_interceptors = interceptors.ToList();
}
public void AfterTransactionBegin(ITransaction tx)
{
_interceptors.ForEach(x => x.AfterTransactionBegin(tx));
}
public void AfterTransactionCompletion(ITransaction tx)
{
_interceptors.ForEach(x => x.AfterTransactionCompletion(tx));
}
public void BeforeTransactionCompletion(ITransaction tx)
{
_interceptors.ForEach(x => x.BeforeTransactionCompletion(tx));
}
public int[] FindDirty(object entity, object id, object[] currentState,
object[] previousState, string[] propertyNames, IType[] types)
{
var results = _interceptors
.Select(interceptor => interceptor.FindDirty(entity, id,
currentState, previousState, propertyNames, types))
.Where(result => result != null)
.SelectMany(x => x)
.Distinct()
.ToArray();
return !results.Any() ? null : results;
}
public object GetEntity(string entityName, object id)
{
return _interceptors
.Select(interceptor => interceptor.GetEntity(entityName, id))
.FirstOrDefault(result => result != null);
}
public string GetEntityName(object entity)
{
return _interceptors
.Select(interceptor => interceptor.GetEntityName(entity))
.FirstOrDefault(result => result != null);
}
public object Instantiate(string entityName, EntityMode entityMode, object id)
{
return _interceptors
.Select(interceptor => interceptor.Instantiate(entityName, entityMode, id))
.FirstOrDefault(result => result != null);
}
public bool? IsTransient(object entity)
{
return _interceptors
.Select(interceptor => interceptor.IsTransient(entity))
.FirstOrDefault(result => result != null);
}
public void OnCollectionRecreate(object collection, object key)
{
_interceptors.ForEach(x => x.OnCollectionRecreate(collection, key));
}
public void OnCollectionRemove(object collection, object key)
{
_interceptors.ForEach(x => x.OnCollectionRemove(collection, key));
}
public void OnCollectionUpdate(object collection, object key)
{
_interceptors.ForEach(x => x.OnCollectionUpdate(collection, key));
}
public void OnDelete(object entity, object id, object[] state,
string[] propertyNames, IType[] types)
{
_interceptors.ForEach(x => x.OnDelete(entity, id, state, propertyNames, types));
}
public bool OnFlushDirty(object entity, object id, object[] currentState,
object[] previousState, string[] propertyNames, IType[] types)
{
return _interceptors.Count(interceptor => interceptor.OnFlushDirty(
entity, id, currentState, previousState, propertyNames, types)) > 0;
}
public bool OnLoad(object entity, object id, object[] state,
string[] propertyNames, IType[] types)
{
return _interceptors.Count(interceptor => interceptor.OnLoad(
entity, id, state, propertyNames, types)) > 0;
}
public SqlString OnPrepareStatement(SqlString sql)
{
return _interceptors.Aggregate(sql, (current, interceptor) =>
interceptor.OnPrepareStatement(current));
}
public bool OnSave(object entity, object id, object[] state,
string[] propertyNames, IType[] types)
{
return _interceptors.Count(interceptor => interceptor.OnSave(
entity, id, state, propertyNames, types)) > 0;
}
public void PostFlush(ICollection entities)
{
_interceptors.ForEach(x => x.PostFlush(entities));
}
public void PreFlush(ICollection entities)
{
_interceptors.ForEach(x => x.PreFlush(entities));
}
public void SetSession(ISession session)
{
_interceptors.ForEach(x => x.SetSession(session));
}
}
using System.Collections;
using NHibernate;
using NHibernate.SqlCommand;
using NHibernate.Type;
using NSubstitute;
using NUnit.Framework;
using Sentric.BackOffice.Infrastructure.Data.Orm.NHibernate;
using Should;
[TestFixture]
public class CompositeInterceptorTests
{
[Test]
public void Should_call_after_transaction_begin()
{
var interceptor1 = Substitute.For<IInterceptor>();
var interceptor2 = Substitute.For<IInterceptor>();
var transaction = Substitute.For<ITransaction>();
var interceptor = new CompositeInterceptor(new[] { interceptor1, interceptor2 });
interceptor.AfterTransactionBegin(transaction);
interceptor1.Received().AfterTransactionBegin(transaction);
interceptor2.Received().AfterTransactionBegin(transaction);
}
[Test]
public void Should_call_after_transaction_completion()
{
var interceptor1 = Substitute.For<IInterceptor>();
var interceptor2 = Substitute.For<IInterceptor>();
var transaction = Substitute.For<ITransaction>();
var interceptor = new CompositeInterceptor(new[] { interceptor1, interceptor2 });
interceptor.AfterTransactionCompletion(transaction);
interceptor1.Received().AfterTransactionCompletion(transaction);
interceptor2.Received().AfterTransactionCompletion(transaction);
}
[Test]
public void Should_call_before_transaction_completion()
{
var interceptor1 = Substitute.For<IInterceptor>();
var interceptor2 = Substitute.For<IInterceptor>();
var transaction = Substitute.For<ITransaction>();
var interceptor = new CompositeInterceptor(new[] { interceptor1, interceptor2 });
interceptor.BeforeTransactionCompletion(transaction);
interceptor1.Received().BeforeTransactionCompletion(transaction);
interceptor2.Received().BeforeTransactionCompletion(transaction);
}
[Test]
public void Should_call_finddirty_on_all_interceptors()
{
var interceptor1 = Substitute.For<IInterceptor>();
var interceptor2 = Substitute.For<IInterceptor>();
var interceptor3 = Substitute.For<IInterceptor>();
var entity = new object();
var id = new object();
var currentState = new object[] { 0 };
var previousState = new object[] { 0 };
var propertyNames = new[] { "Id" };
var types = new[] { Substitute.For<IType>() };
interceptor1.FindDirty(entity, id, currentState, previousState, propertyNames, types).Returns(new [] { 1, 2 });
interceptor2.FindDirty(entity, id, currentState, previousState, propertyNames, types).Returns(new[] { 2, 3 });
interceptor3.FindDirty(entity, id, currentState, previousState, propertyNames, types).Returns((int[])null);
var interceptor = new CompositeInterceptor(new[] { interceptor1, interceptor2 });
interceptor.FindDirty(entity, id, currentState, previousState, propertyNames, types)
.ShouldEqual(new [] { 1, 2, 3 });
}
[Test]
public void Should_return_null_when_finddirty_returns_no_results()
{
var interceptor1 = Substitute.For<IInterceptor>();
var interceptor2 = Substitute.For<IInterceptor>();
var entity = new object();
var id = new object();
var currentState = new object[] { 0 };
var previousState = new object[] { 0 };
var propertyNames = new[] { "Id" };
var types = new[] { Substitute.For<IType>() };
interceptor1.FindDirty(entity, id, currentState, previousState, propertyNames, types).Returns((int[])null);
interceptor2.FindDirty(entity, id, currentState, previousState, propertyNames, types).Returns(new int[] { });
var interceptor = new CompositeInterceptor(new[] { interceptor1, interceptor2 });
interceptor.FindDirty(entity, id, currentState,
previousState, propertyNames, types).ShouldBeNull();
}
[Test]
public void Should_call_getentity_first_interceptor_valid()
{
var interceptor1 = Substitute.For<IInterceptor>();
var interceptor2 = Substitute.For<IInterceptor>();
var entityName = string.Empty;
var id = new object();
interceptor1.GetEntity(entityName, id).Returns(new object());
var interceptor = new CompositeInterceptor(new[] { interceptor1, interceptor2 });
interceptor.GetEntity(entityName, id);
interceptor1.Received().GetEntity(entityName, id);
interceptor2.DidNotReceive().GetEntity(entityName, id);
}
[Test]
public void Should_call_getentity_second_interceptor_valid()
{
var interceptor1 = Substitute.For<IInterceptor>();
var interceptor2 = Substitute.For<IInterceptor>();
var entityName = string.Empty;
var id = new object();
interceptor2.GetEntity(entityName, id).Returns(new object());
var interceptor = new CompositeInterceptor(new[] { interceptor1, interceptor2 });
interceptor.GetEntity(entityName, id);
interceptor1.Received().GetEntity(entityName, id);
interceptor2.Received().GetEntity(entityName, id);
}
[Test]
public void Should_call_get_entity_name_first_interceptor_valid()
{
var interceptor1 = Substitute.For<IInterceptor>();
var interceptor2 = Substitute.For<IInterceptor>();
var entity = new object();
interceptor1.GetEntityName(entity).Returns(string.Empty);
var interceptor = new CompositeInterceptor(new[] { interceptor1, interceptor2 });
interceptor.GetEntityName(entity);
interceptor1.Received().GetEntityName(entity);
interceptor2.DidNotReceive().GetEntityName(entity);
}
[Test]
public void Should_call_get_entity_name_second_interceptor_valid()
{
var interceptor1 = Substitute.For<IInterceptor>();
var interceptor2 = Substitute.For<IInterceptor>();
var entity = new object();
interceptor1.GetEntityName(entity).Returns((string)null);
interceptor2.GetEntityName(entity).Returns(string.Empty);
var interceptor = new CompositeInterceptor(new[] { interceptor1, interceptor2 });
interceptor.GetEntityName(entity);
interceptor1.Received().GetEntityName(entity);
interceptor2.Received().GetEntityName(entity);
}
[Test]
public void Should_call_instantiate_first_interceptor_valid()
{
var interceptor1 = Substitute.For<IInterceptor>();
var interceptor2 = Substitute.For<IInterceptor>();
var entityName = string.Empty;
const EntityMode entityMode = EntityMode.Map;
var id = new object();
interceptor1.Instantiate(entityName, entityMode, id).Returns(new object());
var interceptor = new CompositeInterceptor(new[] { interceptor1, interceptor2 });
interceptor.Instantiate(entityName, entityMode, id);
interceptor1.Received().Instantiate(entityName, entityMode, id);
interceptor2.DidNotReceive().Instantiate(entityName, entityMode, id);
}
[Test]
public void Should_call_instantiate_second_interceptor_valid()
{
var interceptor1 = Substitute.For<IInterceptor>();
var interceptor2 = Substitute.For<IInterceptor>();
var entityName = string.Empty;
const EntityMode entityMode = EntityMode.Map;
var id = new object();
interceptor2.Instantiate(entityName, entityMode, id).Returns(new object());
var interceptor = new CompositeInterceptor(new[] { interceptor1, interceptor2 });
interceptor.Instantiate(entityName, entityMode, id);
interceptor1.Received().Instantiate(entityName, entityMode, id);
interceptor2.Received().Instantiate(entityName, entityMode, id);
}
[Test]
public void Should_call_istransient_first_interceptor_valid()
{
var interceptor1 = Substitute.For<IInterceptor>();
var interceptor2 = Substitute.For<IInterceptor>();
var entity = new object();
interceptor1.IsTransient(entity).Returns(true);
var interceptor = new CompositeInterceptor(new[] { interceptor1, interceptor2 });
interceptor.IsTransient(entity);
interceptor1.Received().IsTransient(entity);
interceptor2.DidNotReceive().IsTransient(entity);
}
[Test]
public void Should_call_istransient_second_interceptor_valid()
{
var interceptor1 = Substitute.For<IInterceptor>();
var interceptor2 = Substitute.For<IInterceptor>();
var entity = new object();
interceptor2.IsTransient(entity).Returns(true);
var interceptor = new CompositeInterceptor(new[] { interceptor1, interceptor2 });
interceptor.IsTransient(entity);
interceptor1.Received().IsTransient(entity);
interceptor2.Received().IsTransient(entity);
}
[Test]
public void Should_call_oncollectionrecreate()
{
var interceptor1 = Substitute.For<IInterceptor>();
var interceptor2 = Substitute.For<IInterceptor>();
var collection = new object();
var key = new object();
var interceptor = new CompositeInterceptor(new[] { interceptor1, interceptor2 });
interceptor.OnCollectionRecreate(collection, key);
interceptor1.Received().OnCollectionRecreate(collection, key);
interceptor2.Received().OnCollectionRecreate(collection, key);
}
[Test]
public void Should_call_oncollectionremove()
{
var interceptor1 = Substitute.For<IInterceptor>();
var interceptor2 = Substitute.For<IInterceptor>();
var collection = new object();
var key = new object();
var interceptor = new CompositeInterceptor(new[] { interceptor1, interceptor2 });
interceptor.OnCollectionRemove(collection, key);
interceptor1.Received().OnCollectionRemove(collection, key);
interceptor2.Received().OnCollectionRemove(collection, key);
}
[Test]
public void Should_call_oncollectionupdate()
{
var interceptor1 = Substitute.For<IInterceptor>();
var interceptor2 = Substitute.For<IInterceptor>();
var collection = new object();
var key = new object();
var interceptor = new CompositeInterceptor(new[] { interceptor1, interceptor2 });
interceptor.OnCollectionUpdate(collection, key);
interceptor1.Received().OnCollectionUpdate(collection, key);
interceptor2.Received().OnCollectionUpdate(collection, key);
}
[Test]
public void Should_call_ondelete()
{
var interceptor1 = Substitute.For<IInterceptor>();
var interceptor2 = Substitute.For<IInterceptor>();
var entity = new object();
var id = new object();
var state = new object[] { 0 };
var propertyNames = new[] { "Id" };
var types = new[] { Substitute.For<IType>() };
var interceptor = new CompositeInterceptor(new[] { interceptor1, interceptor2 });
interceptor.OnDelete(entity, id, state, propertyNames, types);
interceptor1.Received().OnDelete(entity, id, state, propertyNames, types);
interceptor2.Received().OnDelete(entity, id, state, propertyNames, types);
}
[Test]
public void Should_call_onflushdirty_false()
{
var interceptor1 = Substitute.For<IInterceptor>();
var interceptor2 = Substitute.For<IInterceptor>();
var entity = new object();
var id = new object();
var currentState = new object[] { 0 };
var previousState = new object[] { 0 };
var propertyNames = new[] { "Id" };
var types = new[] { Substitute.For<IType>() };
interceptor1.OnFlushDirty(entity, id, currentState, previousState, propertyNames, types).Returns(false);
interceptor2.OnFlushDirty(entity, id, currentState, previousState, propertyNames, types).Returns(false);
var interceptor = new CompositeInterceptor(new[] { interceptor1, interceptor2 });
interceptor.OnFlushDirty(entity, id, currentState, previousState, propertyNames, types).ShouldBeFalse();
interceptor1.Received().OnFlushDirty(entity, id, currentState, previousState, propertyNames, types);
interceptor2.Received().OnFlushDirty(entity, id, currentState, previousState, propertyNames, types);
}
[Test]
public void Should_call_onflushdirty_true()
{
var interceptor1 = Substitute.For<IInterceptor>();
var interceptor2 = Substitute.For<IInterceptor>();
var entity = new object();
var id = new object();
var currentState = new object[] { 0 };
var previousState = new object[] { 0 };
var propertyNames = new[] { "Id" };
var types = new[] { Substitute.For<IType>() };
interceptor1.OnFlushDirty(entity, id, currentState, previousState, propertyNames, types).Returns(false);
interceptor2.OnFlushDirty(entity, id, currentState, previousState, propertyNames, types).Returns(true);
var interceptor = new CompositeInterceptor(new[] { interceptor1, interceptor2 });
interceptor.OnFlushDirty(entity, id, currentState, previousState, propertyNames, types).ShouldBeTrue();
interceptor1.Received().OnFlushDirty(entity, id, currentState, previousState, propertyNames, types);
interceptor2.Received().OnFlushDirty(entity, id, currentState, previousState, propertyNames, types);
}
[Test]
public void Should_call_onload_false()
{
var interceptor1 = Substitute.For<IInterceptor>();
var interceptor2 = Substitute.For<IInterceptor>();
var entity = new object();
var id = new object();
var state = new object[] { 0 };
var propertyNames = new[] { "Id" };
var types = new[] { Substitute.For<IType>() };
interceptor1.OnLoad(entity, id, state, propertyNames, types).Returns(false);
interceptor2.OnLoad(entity, id, state, propertyNames, types).Returns(false);
var interceptor = new CompositeInterceptor(new[] { interceptor1, interceptor2 });
interceptor.OnLoad(entity, id, state, propertyNames, types).ShouldBeFalse();
interceptor1.Received().OnLoad(entity, id, state, propertyNames, types);
interceptor2.Received().OnLoad(entity, id, state, propertyNames, types);
}
[Test]
public void Should_call_onload_true()
{
var interceptor1 = Substitute.For<IInterceptor>();
var interceptor2 = Substitute.For<IInterceptor>();
var entity = new object();
var id = new object();
var state = new object[] { 0 };
var propertyNames = new[] { "Id" };
var types = new[] { Substitute.For<IType>() };
interceptor1.OnLoad(entity, id, state, propertyNames, types).Returns(false);
interceptor2.OnLoad(entity, id, state, propertyNames, types).Returns(true);
var interceptor = new CompositeInterceptor(new[] { interceptor1, interceptor2 });
interceptor.OnLoad(entity, id, state, propertyNames, types).ShouldBeTrue();
interceptor1.Received().OnLoad(entity, id, state, propertyNames, types);
interceptor2.Received().OnLoad(entity, id, state, propertyNames, types);
}
[Test]
public void Should_call_onpreparestatement()
{
var interceptor1 = Substitute.For<IInterceptor>();
var interceptor2 = Substitute.For<IInterceptor>();
var sql = new SqlString();
var sql1 = SqlString.Parse("SELECT name FROM sys.tables");
var sql2 = SqlString.Parse("SELECT name FROM sys.tables UNION SELECT name FROM sys.columns");
interceptor1.OnPrepareStatement(sql).Returns(sql1);
interceptor2.OnPrepareStatement(sql1).Returns(sql2);
var interceptor = new CompositeInterceptor(new[] { interceptor1, interceptor2 });
interceptor.OnPrepareStatement(sql).ShouldEqual(sql2);
interceptor1.Received().OnPrepareStatement(sql);
interceptor2.Received().OnPrepareStatement(sql1);
}
[Test]
public void Should_call_onsave_false()
{
var interceptor1 = Substitute.For<IInterceptor>();
var interceptor2 = Substitute.For<IInterceptor>();
var entity = new object();
var id = new object();
var state = new object[] { 0 };
var propertyNames = new[] { "Id" };
var types = new[] { Substitute.For<IType>() };
interceptor1.OnSave(entity, id, state, propertyNames, types).Returns(false);
interceptor2.OnSave(entity, id, state, propertyNames, types).Returns(false);
var interceptor = new CompositeInterceptor(new[] { interceptor1, interceptor2 });
interceptor.OnSave(entity, id, state, propertyNames, types).ShouldBeFalse();
interceptor1.Received().OnSave(entity, id, state, propertyNames, types);
interceptor2.Received().OnSave(entity, id, state, propertyNames, types);
}
[Test]
public void Should_call_onsave_true()
{
var interceptor1 = Substitute.For<IInterceptor>();
var interceptor2 = Substitute.For<IInterceptor>();
var entity = new object();
var id = new object();
var state = new object[] { 0 };
var propertyNames = new[] { "Id" };
var types = new[] { Substitute.For<IType>() };
interceptor1.OnSave(entity, id, state, propertyNames, types).Returns(false);
interceptor2.OnSave(entity, id, state, propertyNames, types).Returns(true);
var interceptor = new CompositeInterceptor(new[] { interceptor1, interceptor2 });
interceptor.OnSave(entity, id, state, propertyNames, types).ShouldBeTrue();
interceptor1.Received().OnSave(entity, id, state, propertyNames, types);
interceptor2.Received().OnSave(entity, id, state, propertyNames, types);
}
[Test]
public void Should_call_postflush()
{
var interceptor1 = Substitute.For<IInterceptor>();
var interceptor2 = Substitute.For<IInterceptor>();
var entities = Substitute.For<ICollection>();
var interceptor = new CompositeInterceptor(new[] { interceptor1, interceptor2 });
interceptor.PostFlush(entities);
interceptor1.Received().PostFlush(entities);
interceptor2.Received().PostFlush(entities);
}
[Test]
public void Should_call_preflush()
{
var interceptor1 = Substitute.For<IInterceptor>();
var interceptor2 = Substitute.For<IInterceptor>();
var entities = Substitute.For<ICollection>();
var interceptor = new CompositeInterceptor(new[] { interceptor1, interceptor2 });
interceptor.PreFlush(entities);
interceptor1.Received().PreFlush(entities);
interceptor2.Received().PreFlush(entities);
}
[Test]
public void Should_call_setsession()
{
var interceptor1 = Substitute.For<IInterceptor>();
var interceptor2 = Substitute.For<IInterceptor>();
var session = Substitute.For<ISession>();
var interceptor = new CompositeInterceptor(new[] { interceptor1, interceptor2 });
interceptor.SetSession(session);
interceptor1.Received().SetSession(session);
interceptor2.Received().SetSession(session);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment