我编写了简单的拦截器(使用 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?