Skip to content

Instantly share code, notes, and snippets.

@orient-man
Created November 19, 2012 10:04
Show Gist options
  • Save orient-man/4109938 to your computer and use it in GitHub Desktop.
Save orient-man/4109938 to your computer and use it in GitHub Desktop.
Interceptor for managing database connection life cycle
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Castle.DynamicProxy;
namespace MyCompany.Infrastructure
{
class CloseConnectionInterceptor : IInterceptor
{
private static readonly MethodInfo ProxyGenericIteratorMethod =
typeof(CloseConnectionInterceptor)
.GetMethod(
"ProxyGenericIterator",
BindingFlags.NonPublic | BindingFlags.Static);
public void Intercept(IInvocation invocation)
{
var returnType = invocation.Method.ReturnType;
if (returnType == typeof(IEnumerable))
{
HandleNonGenericIteratorInvocation(invocation);
}
else if (returnType.IsGenericType &&
returnType.GetGenericTypeDefinition() == typeof(IEnumerable<>))
{
HandleGenericIteratorInvocation(invocation);
}
else
{
HandleNormalInvocation(invocation);
}
}
private static void HandleNonGenericIteratorInvocation(IInvocation invocation)
{
invocation.Proceed();
invocation.ReturnValue = ProxyNonGenericIterator(
invocation.InvocationTarget,
invocation.ReturnValue as IEnumerable);
}
private static void HandleGenericIteratorInvocation(IInvocation invocation)
{
invocation.Proceed();
var method = ProxyGenericIteratorMethod.MakeGenericMethod(
invocation.Method.ReturnType.GetGenericArguments()[0]);
invocation.ReturnValue = method.Invoke(
null,
new[] { invocation.InvocationTarget, invocation.ReturnValue });
}
private static IEnumerable<T> ProxyGenericIterator<T>(
object target, IEnumerable enumerable)
{
return ProxyNonGenericIterator(target, enumerable).Cast<T>();
}
private static IEnumerable ProxyNonGenericIterator(
object target, IEnumerable enumerable)
{
try
{
foreach (var element in enumerable)
yield return element;
}
finally
{
CloseConnection(target);
}
}
private static void HandleNormalInvocation(IInvocation invocation)
{
try
{
invocation.Proceed();
}
finally
{
CloseConnection(invocation.InvocationTarget);
}
}
private static void CloseConnection(object target)
{
// ...
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment