我通常在想到设计模式中的职责链时, 都会想到A保存B的句柄,比如:
public class A{
private B _b;
void Invoke(){ _b.Invoke() ; }
}
public class B{
private C _c;
void Invoke(){ _c.Invoke() ; }
}
当出现多个对象需要串联起来执行是,就需要bulid 他们的关系,让前面知道后的,这样就必须有个factory或builder 来做这件是事情,我估计把这汇总方式称为静态链式;
下面换种方式来看这个这个问题,我也姑且称它为动态链式; 这应该也是Entlib 拦截器的实现和Castle不一样地方(可能,我已经记不住了);
这么一种方式为:
public delegate void InvokeHandler(GetNextInvokeHandler getNext);
public delegate InvokeHandler GetNextInvokeHandler(); //获取下一个Handler
public class DelegateContainer
{
public IList<InvokeHandler> _listDelegates;
public DelegateContainer() { }
public DelegateContainer(IList<InvokeHandler> list)
: this()
{
_listDelegates = list;
}
public void Invoke(InvokeHandler invoke)
{
if (_listDelegates.Count == 0)
{
//Do mywork
invoke(null);
return;
}
int index = 0;
InvokeHandler delg = _listDelegates[index];
delg(delegate
{
if (_listDelegates.Count > ++index)
{
return _listDelegates[index];
}
return invoke; //Real InvokeHandler;
});
}
}
测试方法如下 :
[TestClass]
public class TestDelegateContainer
{
[TestMethod]
public void TestInvoke()
{
IList<InvokeHandler> handlers = new List<InvokeHandler>();
handlers.Add(new InvokeHandler(InjectInvoke1));
handlers.Add(new InvokeHandler(InjectInvoke2));
handlers.Add(new InvokeHandler(InjectInvoke3));
DelegateContainer container = new DelegateContainer(handlers);
container.Invoke(RealInvoke);
Assert.IsTrue(1 == _resultCount);
Assert.IsTrue(_executionStack.Contains("Real Execution"));
}
private int _resultCount = 0;
public void RealInvoke(GetNextInvokeHandler getNext)
{
//Domywork
_executionStack += "Real Execution";
_resultCount++;
}
private string _executionStack = string.Empty;
public void InjectInvoke1(GetNextInvokeHandler getNext)
{
_executionStack += "Invoke1 >>";
InvokeHandler handler = getNext();
if (handler != null)
{
handler.Invoke(getNext); //这里其实是个关键点
}
//Domywork
}
public void InjectInvoke2(GetNextInvokeHandler getNext)
{
_executionStack += "Invoke2 >>";
InvokeHandler handler = getNext();
if (handler != null)
{
handler.Invoke(getNext);
}
//Domywork
}
public void InjectInvoke3(GetNextInvokeHandler getNext)
{
_executionStack += "Invoke3 >>";
InvokeHandler handler = getNext();
if (handler != null)
{
handler.Invoke(getNext);
}
//Domywork
}
}
输出结果:
resultCount:1
executionStack:'Invoke1 >>Invoke2 >>Invoke3 >>Real Execution'