.NET 4中的访问者模式实现

访问者模式是一种设计模式,它允许一个或者多个操作应用到一组对象上,解耦操作和对象本身。在.NET 3.5中,实现访问者模式并不简单,因为需要基于静态类型来选择调用的Visit方法。但是,随着.NET 4的发布,其动态类型的能力使得实现访问者模式变得更加简单和灵活。

在本文中,将探讨如何在.NET 4中实现访问者模式,包括如何使用动态类型扩展方法。假设读者已经了解双分派访问者模式的基本概念。

使用代码

访问者模式的核心代码如下:

public static void Accept(this object objItem, Visitor objVisitor) { try { ((dynamic)objVisitor).Visit((dynamic)objItem); } catch (RuntimeBinderException excException) { if (objVisitor.Rethrow) throw; objVisitor.Fallback(objItem, excException); } }

通过将objItem和objVisitor声明为动态类型,可以强制执行多态的Visit方法调用。这将选择完全匹配的方法或与objItem最接近的基类匹配的方法。

Visitor类的基本结构如下:

public abstract class Visitor { public bool Rethrow { get; private set; } protected Visitor(bool bRethrow) { Rethrow = bRethrow; } public abstract void Fallback(object objItem, Exception excException); }

用户定义的Visitor需要定义所需的Visit方法,例如:

public class BaseVisitor : Visitor { public BaseVisitor() : base(false) { } public override void Fallback(object objItem, Exception excException) { Console.WriteLine("{0}.Fallback({1}, {2})", this.GetType().Name, objItem.GetType().Name, excException.GetType().Name); } public virtual void Visit(Base objItem) { Console.WriteLine("BaseVisitor.Visit({0})", objItem.GetType().Name); } public virtual void Visit(Derived_A objItem) { Console.WriteLine("BaseVisitor.Visit({0})", objItem.GetType().Name); } }

特定的Visitor可能如下所示:

public class SpecificVisitor : BaseVisitor { public void Visit(Container objItem) { Console.WriteLine("SpecificVisitor.Visit({0})", objItem.GetType().Name); foreach (var objElement in objItem.Elements) { objElement.Accept(this); } } }

访问包含多态数据的容器将按预期工作:

class Program { static void Main(string[] args) { Container c = new Container(); c.Elements.Add(new Base()); c.Elements.Add(new Derived_A()); c.Elements.Add(new Derived_B()); c.Elements.Add(new Derived_A_A()); BaseVisitor objVisitor = new SpecificVisitor(); c.Accept(objVisitor); } }

测试类可能如下所示:

public class Base {} public class Derived_A : Base {} public class Derived_B : Base {} public class Derived_A_A : Derived_A {} public class Container { public IList Elements { get; set; } public Container() { Elements = new List(); } }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485