C# 为两种完全不同的类型编写通用方法
我目前正在为其他人的代码添加附加内容,并且遇到了一个使用PdfSharp dll的PdfBuilder类。在此之前,该类在构造函数中采用了名为C# 为两种完全不同的类型编写通用方法,c#,C#,我目前正在为其他人的代码添加附加内容,并且遇到了一个使用PdfSharp dll的PdfBuilder类。在此之前,该类在构造函数中采用了名为BoxRequest的类型。像这样: public PdfDocument GenerateAddressLabelPdf(int id) { var box = _unitOfWork.BoxRepository.GetById(id); var generator = new PdfBuilder(box
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
}
公共类PdfBuilder
{
私有只读T_pdfType;
公共PdfBuilder(T)
{
_pdfType=t;
}
//额外的课程内容
}
但是现在我有点困惑,我应该如何使GetText
方法通用,因为我需要为每种类型呈现特定的行
此时,我想我可以将类型传递给
GetText
,然后检查类型并根据类型附加不同的行,但它似乎不再是真正的泛型了?我不认为泛型是处理此问题的最佳方法
如果所有这些不同之处都是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
使用它(这将是一种更干净的方式)
你不太可能需要仿制药。您需要从BoxRequest和FileRequest中提取接口,或者\并为它们创建单独的PdfBuilder类(当然是从其中一个类继承)。也许你可以让它成为一个由所有具体对象实现的接口?如果所有不同之处都是
GetText
那么覆盖BoxRequest
和其他类ToString
方法,而完全不关心类型如何?您可以将GetText()
替换为某个input.ToString()
否则,将GetText()
提取到一个接口,并让这两个类以适当的方式实现FileRequest
对象是否具有名称
、部门
和位置.LocationName
属性,就像BoxRequest
?也就是说:打印的方法是完全相同还是不同?还有一种方法是将生成文本的函数传递给构造函数:public PdfBuilder(Func textBuilder)。毕竟,您的PdfBuilder并不关心特定的需求(至少在显示的代码中)。它所关心的只是提供一些文本。我个人赞成用GetText()
方法声明一个新的IPdfPrintable
接口,以便:1)PdfBuilder
需要该接口的对象(而不是任何对象);2) ToString()
的众所周知的含义没有改变。
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);
// ...
}
}