我一直在努力学习如何在c#中正确使用界面,我想我大多理解应该如何使用它们,但仍然对某些事情感到困惑。
我想创建一个程序,用于从销售订单或发票创建CSV。由于它们非常相似,我想我可以创建一个可用于制作CSV文档的IDocument接口。
class Invoice : IDocument
{
public Address billingAddress { get; set; }
public Address shippingAddress { get; set; }
public Customer customer { get; set; }
public List<DocumentLine> lines { get; set; }
// other class specific info for invoice goes here
}
我可以创建一个方法CreateCSV(IDocument),但我如何处理与销售订单和发票不同的几个字段?这是一个糟糕的接口使用?
答案 0 :(得分:3)
你没有继承接口,你实现它们;在这种情况下,接口是抽象;它说&#34;所有实现此接口的东西都具有以下共同特征(属性,方法等)&#34;
在您的情况下,您发现事实上Invoices
和Sales Orders
并没有完全相同的特征。
因此,从以CSV格式表示它们的角度来看,它并不是一个很好的抽象(尽管对于其他事情,比如计算文档的价值,它是一个很好的抽象)
有很多方法可以解决这个问题,这里有两个(很多)
您可以声明一个ICanDoCSVToo
接口,该接口以某种表示CSV的结构返回文档(让我们说一个包含字段和值集合的CSVFormat
类)。
然后,您可以在Invoices
和Sales Orders
上实现此功能,特别是针对这些用例,当您想将其中任何一种转换为CSV格式时,可以通过ICanDoCSVToo
接口传递它们。
但是,我个人并不喜欢这样,因为您并不真的希望您的业务逻辑与您的导出/格式化逻辑相混淆 - 这违反了SRP。请注意,您可以使用抽象类实现相同的效果,但最终它是相同的概念 - 您允许某人告诉知道自己的类,来完成工作。
你也可以创建一个Factory类 - 让我们说一个CSVFormatterFactory
,它给出一个IDocument
对象来确定要返回的格式化程序 - 这是一个简单的例子
public class CSVFormatterLibrary
{
public ICSVFormatter GetFormatter(IDocument document)
{
//we've added DocType to IDocument to identify the document type.
if(document.DocType==DocumentTypes.Invoice)
{
return new InvoiceCSVFormatter(document);
}
if (document.DocType==DocumentTypes.SalesOrders)
{
return new SalesOrderCSVFormatter(document);
}
//And so on
}
}
实际上,您可能会使这个通用并使用IOC库来担心您将返回哪个具体实现,但它是相同的概念。
然后,各个格式化程序本身可以将IDocument
强制转换为正确的具体类型,然后执行生成该特定类型的CSV表示所需的任何内容。
还有其他方法可以解决这个问题,但工厂选项相当简单,在您考虑其他选项时应该让您启动并运行。