Last active
February 18, 2020 10:06
-
-
Save mikeobrien/cad8e66456d45ff0a5e2 to your computer and use it in GitHub Desktop.
NHibernate Composite Interceptor
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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