2016-11-14 2 views
2

В настоящее время я добавляю дополнения к чужому коду и сталкиваюсь с классом PdfBuilder, который использует dll PdfSharp. До этого момента класс взял в конструкторе тип, называемый BoxRequest. как так:Написание общего метода для двух совершенно разных типов

public PdfDocument GenerateAddressLabelPdf(int id) 
    { 
     var box = _unitOfWork.BoxRepository.GetById(id); 
     var generator = new PdfBuilder(box); 
     return generator.BuildPdfDocument(); 
    } 

И PdfBuilder класса выглядит следующим образом:

public class PdfBuilder 
    { 
     private readonly BoxRequest _boxRequest; 

     public PdfBuilder(BoxRequest boxRequest) 
     { 
      _boxRequest = boxRequest; 
     } 

     public PdfDocument BuildPdfDocument() 
     { 
      PdfDocument pdfDocument = new PdfDocument(); 

      PdfPage page = pdfDocument.AddPage(); 
      page.Orientation = PageOrientation.Landscape; 

      XGraphics gfx = XGraphics.FromPdfPage(page); 
      XFont font = new XFont("Arial", 40, XFontStyle.Regular); 
      XTextFormatter tf = new XTextFormatter(gfx); 
      XRect rect = new XRect(0, (page.Height/4), page.Width, page.Height); 
      gfx.DrawRectangle(XBrushes.White, rect); 
      tf.Alignment = XParagraphAlignment.Center; 
      tf.DrawString(GetText(), font, XBrushes.Black, rect);   

      return pdfDocument; 
     } 

     private string GetText() 
     { 
      StringBuilder sb = new StringBuilder(); 
      sb.AppendLine(_boxRequest.Name); 
      sb.AppendLine(_boxRequest.Department); 
      sb.AppendLine(_boxRequest.Location.LocationName); 
      return sb.ToString(); 
     } 
    } 

Так как вы можете видеть свойство, используемое в GetText взяты из FileRequest типа.

теперь мне нужно использовать этот класс снова, на этот раз для нового типа под названием FileRequest, как только я сделал призыв к этому классу и увидел, что это только берет BoxRequest я думал, что это может быть хорошей вещью, чтобы сделать общие ,

До сих пор я изменил класс так:

public class PdfBuilder<T> 
    { 
     private readonly T _pdfType; 

     public PdfBuilder(T t) 
     { 
      _pdfType = t; 
     } 

     //additional class stuff 
    } 

Но теперь я немного запутался, как я должен сделать метод GetText родовым, как мне нужно, чтобы сделать определенные строки для каждого тип.

На данный момент я думаю, что могу передать тип GetText, а затем проверить тип и добавить разные строки в зависимости от типа, но похоже, что он больше не является общим?

+1

Вряд ли вам нужны дженерики. Вам либо нужно извлечь интерфейс из BoxRequest и FileRequest, либо \ и создать для них отдельные классы PdfBuilder (наследуя от одного из них). – Evk

+1

Возможно, вы можете сделать интерфейс T реализованным всеми вашими конкретными объектами? –

+1

, если все это отличается от 'GetText', как об переопределении' BoxRequest' и других классов 'ToString'method и вообще не заботящихся о типе? Вы можете заменить 'GetText()' на sth. 'input.ToString()' иначе, извлечь 'GetText()' в интерфейс и позволить двум курсовым классам реализовать это соответствующим образом. – nozzleman

ответ

3

Я не думаю, что дженерики являются лучшим способом обработки этой проблемы ...

Если все Thats отличается GetText самый простой (не лучший) способ решить эту проблему будет переопределение BoxRequest и другие классы ToString() метод и не заботясь о типе вообще.

public class BoxRequest 
{ 
    // ... 

    public override string ToString() 
    { 
     StringBuilder sb = new StringBuilder(); 
     sb.AppendLine(this.Name); 
     sb.AppendLine(this.Department); 
     sb.AppendLine(this.Location.LocationName); 
     return sb.ToString(); 
    } 
} 

public class PdfBuilder 
{ 
    private readonly object request; 

    public PdfBuilder(object request) 
    { 
     this.request = request; 
    } 

    public PdfDocument BuildPdfDocument() 
    { 
     // ... 

     tf.DrawString(request.ToString(), font, XBrushes.Black, rect);   

     // ... 
    } 

} 

Таким образом, вы можете использовать класс для PDF любого объекта. Если это для вас общее (для меня это так), вы можете извлечь интерфейс для ToString()/GetText() и позволить вашему PdfBuilder потреблять это (что было бы более чистым IMO).

public interface IPdfConvertible 
{ 
    public string GetText() 
} 

// same for FileRequest... 
public class BoxRequest : IPdfConvertible 
{ 
    // ... 

    public string GetText() 
    { 
     StringBuilder sb = new StringBuilder(); 
     sb.AppendLine(this.Name); 
     sb.AppendLine(this.Department); 
     sb.AppendLine(this.Location.LocationName); 
     return sb.ToString(); 
    } 
} 

public class PdfBuilder 
{ 
    private readonly IPdfConvertible request; 

    public PdfBuilder(IPdfConvertible request) 
    { 
     this.request = request; 
    } 

    public PdfDocument BuildPdfDocument() 
    { 
     // ... 

     tf.DrawString(request.GetText(), font, XBrushes.Black, rect);   

     // ... 
    } 
} 
+0

Я лично выступаю за объявление нового интерфейса «IPdfPrintable» с помощью метода «GetText()», так что: 1) «PdfBuilder» требует объект этого интерфейса (а не какой-либо объект); 2) хорошо известное значение 'ToString()' не изменяется. –

+0

Я просто редактировал exaccty, что: D – nozzleman

+0

Делает смысл, спасибо! – JsonStatham