我正在重构一个软件,试图使其更易于测试/DI 友好,并使其更具可扩展性。原始代码依赖于继承,但我认为装饰器会是一种更灵活的设计,因为我希望组件的最终用户能够在我创建的某些层下方插入层。
但是,我遇到了瓶颈,因为基类中的一些代码将 this
传递给了一些方法。使用继承这不会成为问题,因为 this
将引用顶层类型,但我在尝试弄清楚如何使用装饰器使其工作时遇到了麻烦。这是一个例子:
public interface INode
{
bool IsReadOnly { get; }
void DoSomething();
}
public class Node : INode
{
public Node(ISomeFactory someFactory)
{
if (someFactory == null)
throw new ArgumentNullException("someFactory");
this.someFactory = someFactory;
}
private readonly ISomeFactory someFactory;
public bool IsReadOnly { get { return false; } }
public void DoSomething()
{
// Some implementation code here
// This factory doesn't get an instance of the decorator type
// when it is in use - this is a problem
var someInstance = someFactory.Create(this);
// More code here...
}
}
public class LockableNode : INode
{
public LockableNode(INode node, ILockingService lockingService)
{
if (node == null)
throw new ArgumentNullException("node");
if (lockingService == null)
throw new ArgumentNullException("lockingService");
this.innerNode = node;
this.lockingService = lockingService
}
private readonly INode innerNode;
private readonly ILockingService lockingService;
public bool IsReadOnly { get { return lockingService.IsReadOnly; } }
public void DoSomething()
{
if (this.IsReadOnly)
throw new InvalidOperationException("Node is read-only");
this.innerNode.DoSomething();
}
}
然后我的工厂做这样的事情:
var someFactory = new SomeConcreteFactory();
var lockingService = new LockingService();
var node = new Node(someFactory);
var lockableNode = new LockableNode(node, lockingService);
return lockableNode;
我的评论所概述的问题是,我试图装饰的代码中的某些地方,当前对象作为参数传递给其他方法,我需要一个装饰器对象的实例,当它在使用中时而不是当前对象。除了重新实现将 this
传递到装饰器类中的工厂的代码之外,是否可以采取一些措施来解决此问题?
最佳答案
使实际的 doSomething
成为需要装饰对象作为参数的方法:
节点
public void DoSomething()
{
this.DoSomethingWith(this)
}
public void DoSomethingWith(INode it)
{
// ...
var someInstance = someFactory.Create(it);
// ...
}
可锁定节点
public void DoSomething()
{
this.innerNode.DoSomethingWith(this);
}
public void DoSomethingWith(INode it)
{
this.innerNode.DoSomethingWith(it);
}
编辑:当然,您也必须更改界面。
public interface INode
{
bool IsReadOnly { get; }
void DoSomething();
void DoSomethingWith(INode it);
}
关于c# - 如何修复其根类需要装饰器实例的装饰器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14831534/