Answers:
您太花哨的概念太过早了。泛型-当您看到案例时,可以使用它们,但不要担心。工厂模式-为此还具有太多的灵活性(并增加了混乱)。
把事情简单化。使用基本做法。
尝试想象一下在进行XML读取与CSV读取之间的共同点。诸如下一条记录,下一行之类的内容。由于可能会添加新格式,因此请尝试想象待确定格式与已知格式的共性。使用此通用性,定义所有格式都必须遵守的“接口”或合同。尽管他们坚持共同立场,但他们都有各自特定的内部规则。
为了验证数据,请尝试提供一种轻松插入新的或不同的验证器代码块的方法。因此,再次尝试定义一个接口,每个负责特定类型数据构造的验证器均应遵守合同。
对于创建数据结构,无论谁设计建议的输出对象,您可能都会受到约束。尝试弄清楚数据对象的下一步是什么,通过了解最终用途可以进行任何优化。例如,如果您知道对象将在交互式应用程序中使用,则可以通过提供对象的“总和”或计数或其他种类的派生信息来帮助该应用程序的开发人员。
我会说大多数都是模板模式或策略模式。整个项目将是一个Adapter模式。
显而易见的是应用策略模式。具有通用的基类ReadStrategy
,对于每种输入格式,都有一个子类,例如XmlReadStrategy
,CSVReadStrategy
等等。这将使您可以独立于验证处理和输出处理来更改导入处理。
根据详细信息,也可以保留导入通用的大部分内容,而仅交换输入处理的一部分内容(例如,读取一条记录)。这可能会导致您进入“ 模板方法”模式。
对于将来可能需要扩展的导入实用程序,合适的模式是使用MEF-您可以通过从惰性列表中动态加载所需的转换器来保持较低的内存使用量,创建装饰有属性的MEF导入可以帮助您为要尝试执行的导入选择正确的转换器,并提供一种简便的方法来区分不同的导入类。
可以使用一些标准方法来构建每个MEF部件,以使其满足导入接口,这些标准方法会将导入文件的行转换为输出数据,或者使用基本功能覆盖基类。
MEF是用于创建插件体系结构的框架-它是如何构建Outlook和Visual Studio的,而VS中所有这些可爱的扩展都是MEF的一部分。
要构建MEF(托管可扩展性框架)应用,请先添加对 System.ComponentModel.Composition
定义接口以指定转换器将执行的操作
public interface IImportConverter
{
int UserId { set; }
bool Validate(byte[] fileData, string fileName, ImportType importType);
ImportResult ImportData(byte[] fileData, string fileName, ImportType importType);
}
这可以用于要导入的所有文件类型。
将属性添加到新类中,以定义该类将“导出”的内容
[Export(typeof(IImportConverter))]
[MyImport(ImportType.Address, ImportFileType.CSV, "4eca4a5f-74e0")]
public class ImportCSVFormat1 : ImportCSV, IImportConverter
{
...interface methods...
}
这将定义一个类,该类将导入CSV文件(特定格式:Format1),并具有用于设置MEF导出属性元数据的自定义属性。您要为要导入的每种格式或文件类型重复此操作。您可以使用以下类来设置自定义属性:
[MetadataAttribute]
[AttributeUsage(AttributeTargets.All, AllowMultiple = false)]
public class ImportAttribute : ExportAttribute
{
public ImportAttribute(ImportType importType, ImportFileType fileType, string customerUID)
: base(typeof(IImportConverter))
{
ImportType = importType;
FileType = fileType;
CustomerUID = customerUID;
}
public ImportType ImportType { get; set; }
public ImportFileType FileType { get; set; }
public string CustomerUID { get; set; }
}
要实际使用MEF转换器,您需要导入在运行转换代码时创建的MEF部件:
[ImportMany(AllowRecomposition = true)]
protected internal Lazy<IImportConverter, IImportMetadata>[] converters { get; set; }
AggregateCatalog catalog = new AggregateCatalog();
catalog
从文件夹收集零件,默认为应用程序位置。
converters
是进口的MEF零件的懒惰清单
然后,当您知道要转换的文件类型(importFileType
和importType
)时,可以从导入的零件列表中获取转换器。converters
var tmpConverter = (from x in converters
where x.Metadata.FileType == importFileType
&& x.Metadata.ImportType == importType
&& (x.Metadata.CustomerUID == import.ImportDataCustomer.CustomerUID)
select x).OrderByDescending(x => x.Metadata.CustomerUID).FirstOrDefault();
if (tmpConverter != null)
{
var converter = (IImportConverter)tmpConverter.Value;
result = converter.ImportData(import.ImportDataFile, import.ImportDataFileName, importType);
....
}
的调用converter.ImportData
将使用导入的类中的代码。
可能看起来像很多代码,可能需要花费一些时间来弄清正在发生的事情,但是在添加新的转换器类型时它非常灵活,甚至可以允许您在运行时添加新的转换器类型。
-1
我不接受,因为基本思想仍然有意义,并且依赖于IImportConverter
界面所统治的策略模式。
解决该问题的合适设计模式是什么?
C#习惯用法涉及使用内置的序列化框架来执行此操作。您可以使用元数据为对象添加注释,然后实例化使用这些注释的各种序列化程序,以将数据提取为正确的格式,反之亦然。
Xml,JSON和二进制形式是最常见的形式,但是如果其他形式已经以包装好的形式供您使用,我也不会感到惊讶。