データベース接続のライフサイクルを処理するために、(Castle.DynamicProxyを使用して)単純なインターセプターを作成しました。つまり、すべてのサービスには、最初の使用時に新しいサービスを開くConnectionプロパティがあります。各メソッド呼び出しの後、接続は自動的に閉じられます。
class CloseConnectionInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
try
{
invocation.Proceed();
}
finally
{
var hasConnection = invocation.InvocationTarget as IHasConnection;
if (hasConnection.IsConnectionOpen)
{
hasConnection.Connection.Dispose();
hasConnection.Connection = null;
}
}
}
}
interface IHasConnection
{
bool IsConnectionOpen { get; }
Connection Connection { get; set; }
}
イテレータを返すメソッドを除いて、うまく機能します。
[Test]
public void ConnectionClosedByProxy()
{
// arrange
var service = new MyService();
var proxy = new ProxyGenerator()
.CreateInterfaceProxyWithTarget<IMyService>(
service, new CloseConnectionInterceptor());
// act
proxy.GetList();
// assert: works!!!
Assert.IsFalse(service.IsConnectionOpen);
}
[Test]
public void IteratorLeavesOpenConnection()
{
// arrange
var service = new MyService();
var proxy = new ProxyGenerator()
.CreateInterfaceProxyWithTarget<IMyService>(
service, new CloseConnectionInterceptor());
// act
proxy.GetEnumerable().ToList();
// assert: bad, bad, bad!
Assert.IsTrue(service.IsConnectionOpen);
}
ここで完全な例を参照してください:https ://gist.github.com/4087483
GetEnumerableメソッド内に"using(new Connection())"ステートメントがある場合、それは期待どおりに機能します-イテレーターへの最後のアクセス後に接続が閉じられます。この瞬間を迎撃機で捕まえることは可能ですか?または、メソッドだけでなく、結果のIEnumerableもプロキシする必要がありますか?