Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Element base class
- public abstract class Element {
- // I am returning an Element here (different from a "normal" GoF implementation)
- internal abstract Element Accept(IVisitor visitor);
- }
- // Visitor base class
- public abstract class VisitorBase: IVisitor
- {
- // Again, return an Element
- // This is so that each visitor can choose to return a different type
- // than the visited Element
- public virtual Element Visit(Element element)
- {
- element = element.Accept(this);
- return element;
- }
- // Another departure from vanilla visitor: Visit just this element
- // (and don't recurse)
- public virtual Element VisitNonRecursive(Element element)
- {
- return element;
- }
- // These can be individually overridden, and I have added these for transforming
- // one type of Element into another
- public virtual Element VisitNonRecursive(LeafElementA leafElementA)
- {
- return VisitNonRecursive(leafElementA as Element);
- }
- public virtual Element VisitNonRecursive(LeafElementB leafElementB)
- {
- return VisitNonRecursive(leafElementB as Element);
- }
- // ...similar methods for the other elements (removed to reduce clutter in the snippet)
- }
- public class LeafElementA : Element
- {
- internal override Element Accept(IVisitor visitor)
- {
- return visitor.VisitNonRecursive(this);
- }
- }
- // Implementation of Element that contains multiple other Elements
- public class CompositeElement : Element
- {
- public CompositeElement(params Element[] containedElements)
- {
- ContainedElements = containedElements.ToList();
- }
- public ICollection<Element> ContainedElements { get; private set; }
- internal override Element Accept(IVisitor visitor)
- {
- ContainedElements = ContainedElements
- // Recursively visit each child
- .Select(visitor.Visit)
- .ToList();
- // And non-recursively visit this
- return visitor.VisitNonRecursive(this);
- }
- }
- // Implementation of Element that contains exactly two other Elements
- public class BinaryElement : Element
- {
- public BinaryElement(Element left, Element right)
- {
- Left = left;
- Right = right;
- }
- public Element Left { get; private set; }
- public Element Right { get; private set; }
- internal override Element Accept(IVisitor visitor)
- {
- // Recursively visit the children
- Left = visitor.Visit(Left);
- Right = visitor.Visit(Right);
- // And non-recursively visit this
- return visitor.VisitNonRecursive(this);
- }
- }
- // Implementation of Visitor that adds a LeafElementA to any composite element
- public class AddOneMoreVisitor : VisitorBase
- {
- public override Element VisitNonRecursive(MultiCompositeElement multiCompositeElement)
- {
- multiCompositeElement.ContainedElements.Add(new LeafElementA());
- return multiCompositeElement;
- }
- public override Element VisitNonRecursive(BinaryCompositeElement binaryCompositeElement)
- {
- // Here we are able to change the returned type from the visitor
- var result = new MultiCompositeElement(
- binaryCompositeElement.Left,
- binaryCompositeElement.Right,
- new LeafElementA()
- );
- return result;
- }
- // The rest of the recursion-based visiting can be delegated to the base
- }
- internal abstract Element Transform(ITransformer transformer);
- new BinaryElement(null, null).Accept(...)
- interface IVisitor
- {
- //removed from interface
- //(you can still have this method as `protected virtual` in base implementation)
- //Element Visit(Element element);
- Element Visit(BinaryElement element);
- Element Visit(CompositeElement element);
- //etc...
- }
- interface IVisitor
- {
- Element Visit(Element element);
- //removed from interface
- //(you can still have those methods as `protected virtual` in base implementation)
- //Element Visit(BinaryElement element);
- //Element Visit(CompositeElement element);
- }
- public virtual Element Visit(Element element)
- {
- element = element.Accept(this);
- return element;
- }
- public virtual Element Invite(Element element)
- {
- element = element.Accept(this);
- return element;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement