2013-10-17 2 views
0

나는 MigraDoc을 사용하여 pdf 문서를 만듭니다.어떻게 이것을 공장/추상 공장으로 변환 할 수 있습니까?

MigraDoc에서 사용 된 것과 유사한 비즈니스 엔티티가 있습니다.

createRenderer를 들어
  var document = new Document(); 
      var section = document.AddSection();// section is a page in pdf 
      var page = GetPage(1); // get a page from business classes 
      foreach (var content in page.Content) 
      { 
         //var renderer = createRenderer(content); // 
        // get Renderer based on Business type ?? 
        // renderer.Render(section) 
      } 

() 내가 스위치를 사용할 수 있습니다 내 비즈니스 로직에

public class Page{ 
     public List<PageContent> Content { get; set; } 
    } 


    public abstract class PageContent { 

     public int Width { get; set; }  
     public int Height { get; set; } 
     public Margin Margin { get; set; } 
    } 

    public class Paragraph : PageContent{ 
     public string Text { get; set; }  
    } 

    public class Table : PageContent{ 
     public int Rows { get; set; }  
     public int Columns { get; set; } 
     //.... more 
    } 

public interface IPdfRenderer<T> 
{ 
    T Render(MigraDoc.DocumentObjectModel.Section s); 
} 

class ParagraphRenderer 
    : IPdfRenderer<MigraDoc.DocumentObjectModel.Paragraph> 
{ 
    BusinessEntities.PDF.Paragraph paragraph; 

    public ParagraphRenderer(BusinessEntities.PDF.Paragraph p) 
    { 
    paragraph = p; 
    } 

    public MigraDoc.DocumentObjectModel.Paragraph Render(MigraDoc.DocumentObjectModel.Section s) 
    { 
     var paragraph = s.AddParagraph(); // add text from paragraph etc 
     return paragraph; 
    } 
} 


public class TableRenderer : IPdfRenderer<MigraDoc.DocumentObjectModel.Tables.Table> 
{ 
    BusinessEntities.PDF.Table table; 
    public TableRenderer(BusinessEntities.PDF.Table t) 
    { 
     table =t; 
    } 
    public MigraDoc.DocumentObjectModel.Tables.Table Render(Section obj) 
    { 
     var table = obj.AddTable(); 
     //fill table based on table 
    } 
} 

내가 같은 PDF 페이지를 생성 할 각 유형에 대한 클래스를 렌더링있다 case/사전 및 return 유형.

유형에 따라 렌더러를 일반적으로 가져 오거나 만들 수 있습니까?

여기 공장이나 초록 공장을 어떻게 사용할 수 있습니까?

또는 어떤 디자인 패턴이이 문제에 더 잘 맞습니까?

답변

1

열쇠가 유형이 될 공장을 사용할 수 있습니다. this 기사에 몇 가지 예가 있습니다.

IoC를 사용할 여력이 있다면 IoC 엔진이 문자열을 기반으로 어떤 구체적인 클래스를 사용해야하는지 결정하게하면 그에 따라 컨테이너를 구성해야합니다. 이 문자열은 유형 이름이 될 수 있습니다. 나는 ninject을 제안하지만 windsor와 같은 다른 IoC는 작동 할 수 있습니다.

다음은 제네릭 인터페이스가있는 팩터 리를 사용하여 수행 할 수있는 방법의 예입니다. 귀하의 경우에는 전달해야하는 생성자가 있기 때문입니다.

public class Factory<T> 
{ 
    public Factory() 
    { 
     _Mappings = new Dictionary<string,Func<IInterface<T>>>(2); 

     _Mappings.Add("MyClass1",() => new MyClass1() as IInterface<T>); 
     _Mappings.Add("MyClass2",() => new MyClass2() as IInterface<T>); 
    } 
    public IInterface<T> Get(string typeName) 
    { 
     Func<IInterface<T>> func; 
     if (_Mappings.TryGetValue(typeName, out func)) 
     { 
      return func(); 
     } 
     else 
      throw new NotImplementedException(); 
    } 

    readonly Dictionary<string, Func<IInterface<T>>> _Mappings; 
} 

public class MyClass1 : IInterface<int> 
{ 
    public int Method() 
    { 
     throw new NotImplementedException(); 
    } 
} 

public class MyClass2 : IInterface<string> 
{ 
    public string Method() 
    { 
     throw new NotImplementedException(); 
    } 
} 

public interface IInterface<T> 
{ 
    T Method(); 
} 

나는 여전히 IoC가 더 좋다고 생각하지만 이는 유효한 접근 방법입니다.

+0

pls는 설명 할 수 있습니까? 내 상황에 기사를 매핑 할 수 없습니다. – Amitd

+0

다음은 동일한 개념을 사용하지만 유형 이름을 키로 사용하는 팩토리의 예입니다. 제네릭 인터페이스를 제네릭 인터페이스로 대체해야합니다. 공장에서 여분의 paremeter를 전달해야 생성자를 채울 수 있습니다. 공용 클래스 – arturomonriv

+0

공장 { 공장 공개() { _Mappings = 새로운 사전 <문자열 Func을 <는 IInterface >> 2; 새 MyClass1()을 IInterface로 사용하여 _Mappings.Add ("MyClass1",()) ); _ 매핑.Add ("MyClass2",() => 새로운 MyClass2()를 IInterface로 추가하십시오. ); } – arturomonriv

1

인터페이스 정의를 향상시킬 수 있습니다. 제네릭을 반환하고 생성자로 입력을 받아들이는 대신 제네릭을 입력으로 받아들이고이를 반환 할 수 있습니다. 당신이 가진 arutromonriv의 대답 확대 그리고

public interface IPdfRenderer<T> 
{ 
    T Render(MigraDoc.DocumentObjectModel.Section s, T baseContent); 
} 

,

public class DynamicRenderer : IPdfRenderer<PageContent> 
{ 
    public DynamicRenderer(IPdfRenderer<Paragraph> paragraph 
     , IPdfRenderer<Table> table){ 
     //variable assignment 
    } 
    public PageContent Render(MigraDoc.DocumentObjectModel.Section s, PageContent baseContent){ 
     if(baseContent is Paragraph){ return paragraph.Render(s, baseContent as Paragraph); } 
     else{ return table.Render(s, baseContent as Table); } 
    } 
} 

을 수행 할 수 있습니다 당신은 더

var renderer = createRenderer(); // 
foreach (PageContent content in page.Content) 
{ 
    // get Renderer based on Business type ?? 
    renderer.Render(section, content); 
} 
관련 문제