1

모든 노드 객체가 동일한 기본 클래스에서 파생되며 노드를 임의적으로 중첩 할 수있는 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(); 
     } 
    } 
} 

내가 얻을 :

다음은 간단한 예입니다

Baz <Quux=frob> 

Bar <Qux=0> 
Foo <> 
Foo <> 

나는 시도하고 까다로운 대신이 작업을 수행 할 경우

public static string ToText(this Foo foo, int indent = 0) 
{ 
    return ((dynamic)foo).ToText(indent); 
} 

합니다. .. 첫 번째 인쇄가 작동하지만 두 번째 예외는 다음과 같습니다.

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

전적으로 잘못된 접근 방식을 사용하고 있지만 방향을 사용할 수는 있습니다.

+0

를, 그것은 것 적절한 템플릿 엔진을 사용하여 대부분의 작업을 처리 할 수 ​​있습니다. 나는 RazorEngine을 조작 해왔다.하지만 모델을 처리하는 재귀 적 특성에 문제가있다. – qSlug

답변

1

조금 뒤얽힌 후 나는 주제가 Virtual Extension Methods? 인 것을 발견했다.

IFooFormater fooFormater = new FooFormater(); 
Console.WriteLine(bar.ToText(fooFormater)); 

내가 예상 출력을 얻을 : 호출하여 다음

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>