Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/302.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/visual-studio-2010/4.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#_Extension Methods_String Formatting_Template Engine_Derived Class - Fatal编程技术网

C# 在基类集合上迭代时解决子类扩展方法

C# 在基类集合上迭代时解决子类扩展方法,c#,extension-methods,string-formatting,template-engine,derived-class,C#,Extension Methods,String Formatting,Template Engine,Derived Class,我有一个从XML反序列化的模型,其中所有节点对象都派生自同一基类,节点可以(某种程度上)任意嵌套。我正在尝试编写一组模块,这些模块可以将加载的模型转换为各种基于文本的格式。我认为,如果每个这样的模块都是一个扩展类,它将允许我简单地调用Model.ToText()、Model.ToHtml()等,那将是一件好事。但我遇到了一些问题 以下是一个简化的示例: using System; using System.Collections.Generic; using System.Text; name

我有一个从XML反序列化的模型,其中所有节点对象都派生自同一基类,节点可以(某种程度上)任意嵌套。我正在尝试编写一组模块,这些模块可以将加载的模型转换为各种基于文本的格式。我认为,如果每个这样的模块都是一个扩展类,它将允许我简单地调用Model.ToText()、Model.ToHtml()等,那将是一件好事。但我遇到了一些问题

以下是一个简化的示例:

using System;
using System.Collections.Generic;
using System.Text;

namespace Sample
{
    public abstract class Foo
    {
    }

    public class Bar : Foo
    {
        public List<Foo> Children = new List<Foo>();
        public int Qux;
    }

    public class Baz : Foo
    {
        public string Quux;
    }

    public static class Extension
    {
        public static string ToText(this Foo foo, int indent = 0)
        {
            return String.Format("{0}Foo <>\n", new String(' ', indent));
        }

        public static string ToText(this Bar bar, int indent=0)
        {
            StringBuilder sb = new StringBuilder(); 
            sb.Append(String.Format("{0}Bar <Qux={1}>\n", new String(' ', indent), bar.Qux));
            foreach (var child in bar.Children)
            {
                sb.Append(child.ToText(indent + 1));
            }
            return sb.ToString();
        }

        public static string ToText(this Baz baz, int indent=0)
        {
            return String.Format("{0}Baz <Quux={1}>\n", new String(' ', indent), baz.Quux);
        }

    }

    class Program
    {
        static void Main(string[] args)
        {
            Baz baz = new Baz { Quux = "frob" };

            Bar bar = new Bar
                {
                    Children = new List<Foo>()
                        {
                            new Baz {Quux = "fred"},
                            new Bar
                                {
                                    Qux = 11,
                                    Children = new List<Foo>()
                                        {
                                            new Baz() {Quux = "flog"}
                                        }
                                }
                        }
                };

            //This works
            Console.WriteLine(baz.ToText());

            //But this doesn't
            Console.WriteLine(bar.ToText());
            Console.ReadKey();
        }
    }
}
。。。第一次打印有效,但第二次打印给了我一个例外:

{"'Sample.Baz' does not contain a definition for 'ToText'"}

我可能采取了完全错误的方法,但我可以使用一些方向。

经过一番周折,我找到了主题。看起来我可以用访问者模式清晰地解决这个问题:

public interface IFooFormater
{
    string Format(Foo foo, int indent);
    string Format(Bar bar, int indent);
    string Format(Baz baz, int indent);
}

public class FooFormater : IFooFormater
{
    public string Format(Foo foo, int indent)
    {
        return "";
    }

    public string Format(Bar bar, int indent)
    {
        StringBuilder sb = new StringBuilder();
        sb.Append(String.Format("{0}Bar <Qux={1}>\n", new String(' ', indent), bar.Qux));
        foreach (var child in bar.Children)
        {
            sb.Append(this.Format((dynamic)child , indent + 1));
        }
        return sb.ToString();            
    }

    public string Format(Baz baz, int indent)
    {
        return String.Format("{0}Baz <Quux={1}>\n", new String(' ', indent), baz.Quux);
    }
}


public static class Extension
{

    public static string ToText(this Foo foo, IFooFormater fooFormater)
    {
        return fooFormater.Format((dynamic)foo, 0);
    }
}
我得到了预期的输出:

Bar <Qux=0>
 Baz <Quux=fred>
 Bar <Qux=11>
  Baz <Quux=flog>
条
巴兹
酒吧
巴兹

经过一番周折,我找到了主题。看起来我可以用访问者模式清晰地解决这个问题:

public interface IFooFormater
{
    string Format(Foo foo, int indent);
    string Format(Bar bar, int indent);
    string Format(Baz baz, int indent);
}

public class FooFormater : IFooFormater
{
    public string Format(Foo foo, int indent)
    {
        return "";
    }

    public string Format(Bar bar, int indent)
    {
        StringBuilder sb = new StringBuilder();
        sb.Append(String.Format("{0}Bar <Qux={1}>\n", new String(' ', indent), bar.Qux));
        foreach (var child in bar.Children)
        {
            sb.Append(this.Format((dynamic)child , indent + 1));
        }
        return sb.ToString();            
    }

    public string Format(Baz baz, int indent)
    {
        return String.Format("{0}Baz <Quux={1}>\n", new String(' ', indent), baz.Quux);
    }
}


public static class Extension
{

    public static string ToText(this Foo foo, IFooFormater fooFormater)
    {
        return fooFormater.Format((dynamic)foo, 0);
    }
}
我得到了预期的输出:

Bar <Qux=0>
 Baz <Quux=fred>
 Bar <Qux=11>
  Baz <Quux=flog>
条
巴兹
酒吧
巴兹

作为奖励,最好将大部分腿部工作交给合适的模板引擎。我一直在修补RazorEngine,但我在处理模型的递归性方面遇到了问题。作为奖励,最好将大部分工作交给适当的模板引擎。我一直在修补RazorEngine,但在处理模型的递归特性方面遇到了麻烦。
Bar <Qux=0>
 Baz <Quux=fred>
 Bar <Qux=11>
  Baz <Quux=flog>