Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在C语言中实现访问者模式#_C#_Visitor Pattern - Fatal编程技术网

C# 在C语言中实现访问者模式#

C# 在C语言中实现访问者模式#,c#,visitor-pattern,C#,Visitor Pattern,我是这方面的新手,能不能请人帮我一下 我得到了这样一个物体: public class Object { public string Name { get; set; } public object Value { get; set; } public List<Object> Childs { get; set; } } 我的问题是如何创建访问者模式以获得最终字符串: (Name IsEqual 3)And((Nam

我是这方面的新手,能不能请人帮我一下

我得到了这样一个物体:

public class Object
    {
        public string Name { get; set; }
        public object Value { get; set; }
        public List<Object> Childs { get; set; }
    }
我的问题是如何创建访问者模式以获得最终字符串:

(Name IsEqual 3)And((Name IsEqul 5)And(Name IsEqual 6))

这可能不是你想要的。但是在不使用访问者模式的情况下创建所需输出的一种方法是将以下方法添加到
对象
类中,如下所示:

public string Format()
{
    if (Name == "Operator")
    {
        if(Childs == null || Childs.Count != 1)
            throw new Exception("Invalid Childs");

        Object chlid = Childs[0];

        return chlid.Name + " IsEqual " + chlid.Value;

    }

    if (Name == "Method")
    {
        if(Childs == null || Childs.Count == 0)
            throw new Exception("Invalid Childs");

        var str = " " + Value + " ";

        return string.Join(str, Childs.Select(x => "(" +  x.Format() + ")"));
    }

    throw new Exception("Format should only be invoked on Operator/Method");
}

首先,你的结果顺序错误。其次,有时你会错过结果中的括号。最后应该是:

(((Name IsEqual 5) And (Name IsEqual 6)) And (Name IsEqual 3))
要完成此任务,应使用递归函数

  static IEnumerable<string> ReturnString(Obj val)
        {
            foreach (Obj node in val.Childs)
                yield return ConvertToString(node);
        }

        static string ConvertToString(Obj val)
        {
            switch(val.Name)
            {
                case "Operator":
                    {
                        return string.Format("({0} {1} {2})", val.Childs[0].Name, val.Value, val.Childs[0].Value);
                    }
                case "Method":
                    {
                        IEnumerable<string> coll = ReturnString(val);
                        StringBuilder final = new StringBuilder();
                        final.Append("(");

                        IEnumerator<string> e = coll.GetEnumerator();
                        e.MoveNext();
                        final.Append(string.Format("{0}", e.Current, val.Value));

                        while (e.MoveNext())
                        {
                           final.Append(string.Format(" {0} {1}", val.Value, e.Current));
                        }

                        final.Append(")");


                        return final.ToString();
                    }
                case "Name":
                    return  Convert.ToString(val.Value);
           }
           return "-";
        }
静态IEnumerable返回字符串(Obj val)
{
foreach(val.Childs中的Obj节点)
收益-收益转换字符串(节点);
}
静态字符串转换字符串(Obj val)
{
开关(val.Name)
{
案例“操作员”:
{
返回string.Format(({0}{1}{2})”,val.Childs[0]。Name,val.Value,val.Childs[0]。Value);
}
案例“方法”:
{
IEnumerable coll=返回字符串(val);
StringBuilder final=新的StringBuilder();
最后。附加(“”);
IEnumerator e=coll.GetEnumerator();
e、 MoveNext();
Append(string.Format(“{0}”,e.Current,val.Value));
while(如MoveNext())
{
Append(string.Format(“{0}{1}”,val.Value,e.Current));
}
最后。附加(“)”;
返回final.ToString();
}
案例“名称”:
返回Convert.ToString(val.Value);
}
返回“-”;
}
下面是代码中的示例:

string s = ConvertToString(new Obj
            {
                Name = "Method",
                Value = "And",
                Childs = new List<Obj>
                        {
                            new Obj()
                            {
                                Name = "Method",
                                Value = "And",
                                Childs = new List<Obj>
                                {
                                     new Obj()
                                    {
                                        Name = "Operator",
                                        Value = "IsEqual",
                                        Childs = new List<Obj>
                                        {
                                           new Obj()
                                           {
                                               Name="Name",
                                               Value="5",
                                               Childs=null
                                           }
                                        }
                                    },
                                    new Obj()
                                    {
                                    Name = "Operator",
                                        Value = "IsEqual",
                                        Childs = new List<Obj>
                                        {
                                           new Obj()
                                           {
                                               Name="Name",
                                               Value="6",
                                               Childs=null
                                           }
                                        }
                                    }
                                }
                            },
                            new Obj()
                            {
                                Name = "Operator",
                                Value = "IsEqual",
                                Childs = new List<Obj>
                                {
                                   new Obj()
                                   {
                                       Name="Name",
                                       Value="3",
                                       Childs=null
                                   }
                                }
                            }
                        }
            });
string s=ConvertToString(新Obj
{
Name=“方法”,
Value=“And”,
Childs=新列表
{
新Obj()
{
Name=“方法”,
Value=“And”,
Childs=新列表
{
新Obj()
{
Name=“Operator”,
Value=“IsEqual”,
Childs=新列表
{
新Obj()
{
Name=“Name”,
Value=“5”,
Childs=null
}
}
},
新Obj()
{
Name=“Operator”,
Value=“IsEqual”,
Childs=新列表
{
新Obj()
{
Name=“Name”,
Value=“6”,
Childs=null
}
}
}
}
},
新Obj()
{
Name=“Operator”,
Value=“IsEqual”,
Childs=新列表
{
新Obj()
{
Name=“Name”,
Value=“3”,
Childs=null
}
}
}
}
});

要实现访问者模式,您需要两个简单的界面

  • IVisitable
    ,使用
    Accept
    方法将
    IVisitor
    作为参数
  • IVisitor
    具有许多
    访问
    方法,用于
    IVisitable的每个实现
  • 所以访问者模式的基本思想是根据实现的类型动态地改变行为

    对于您的情况,您希望访问的对象(可访问对象)是
    对象
    类,它显然没有不同的派生,您希望根据属性值而不是类型来更改行为。所以访问者模式并不是你真正需要的,我强烈建议你用递归的方法来考虑答案。 但如果您真的想在这里使用访问者模式,它可能看起来像这样

    interface IVisitable { void Accept(IVisitor visitor); }
    
    interface IVisitor {
        void VisitAnd(Object obj);
        void VisitEquals(Object obj);
    }
    
    由于
    对象
    类是一个简单的POCO,我假设您不希望实现接口并向该类中添加方法。因此,您需要一个将
    object
    调整为
    IVisitable

    class VisitableObject : IVisitable {
        private Object _obj;
    
        public VisitableObject(Object obj) { _obj = obj; }
    
        public void Accept(IVisitor visitor) {
            // These ugly if-else are sign that visitor pattern is not right for your model or you need to revise your model.
            if (_obj.Name == "Method" && _obj.Value == "And") {
                visitor.VisitAnd(obj);
            }
            else if (_obj.Name == "Method" && _obj.Value == "IsEqual") {
                visitor.VisitEquals(obj);
            }
            else
                throw new NotSupportedException();
            }
        }
    }
    
    public static ObjectExt {
        public static IVisitable AsVisitable(this Object obj) {
            return new VisitableObject(obj);
        }
    }
    
    最后,访问者实现可能如下所示

    class ObjectVisitor : IVisitor {
        private StringBuilder sb = new StringBuilder();
    
        public void VisitAnd(Object obj) {
            sb.Append("(");
            var and = "";
            foreach (var child in obj.Children) {
                sb.Append(and);
                child.AsVisitable().Accept(this);
                and = "and";
            }
            sb.Append(")");
        }
    
        public void VisitEquals(Object obj) {
            // Assuming equal object must have exactly one child 
            // Which again is a sign that visitor pattern is not bla bla...
            sb.Append("(")
              .Append(obj.Children[0].Name);
              .Append(" Equals ");
              .Append(obj.Children[0].Value);
              .Append(")");
        }
    }
    

    JSON清楚地表示一个令牌树(可能由解析器生成)

    访问者模式使用多态性。

    为了供访问者模式使用,必须对其进行反序列化,以获得具有不同访问行为的对象:

    • MethodToken
    • 操作员停止
      class ObjectVisitor : IVisitor {
          private StringBuilder sb = new StringBuilder();
      
          public void VisitAnd(Object obj) {
              sb.Append("(");
              var and = "";
              foreach (var child in obj.Children) {
                  sb.Append(and);
                  child.AsVisitable().Accept(this);
                  and = "and";
              }
              sb.Append(")");
          }
      
          public void VisitEquals(Object obj) {
              // Assuming equal object must have exactly one child 
              // Which again is a sign that visitor pattern is not bla bla...
              sb.Append("(")
                .Append(obj.Children[0].Name);
                .Append(" Equals ");
                .Append(obj.Children[0].Value);
                .Append(")");
          }
      }
      
      public interface IVisitor
      {
          void Visit(MethodToken token) { /* */ }
          void Visit(OperatorToken token) { /* */ }
          void Visit(NameToken token) { /* */ }
      }
      
      public interface IVisitable
      {
          void Accept(IVisitor visitor);
      }
      
      public class MethodToken : IVisitable
      {
          public void Accept(IVisitor visitor)
          {
              visitor.Visit(this);
          }
      }
      
      public class Token
      {
          public string Name { get; set; }
          public string Value { get; set; }
          public List<Token> Children { get; set; }
      }