使用用户选择的列创建CSV

时间:2015-07-13 12:57:08

标签: c# csv design-patterns

我有一点设计问题。让我们说我有一个包含大量人的项目。我想允许用户使用他选择的信息将这些人导出到CSV文件 例如,他可以选择Id,姓名,电话号码,根据他的选择我会创建文件 当然,有一种简单的方法就像if(idCheckBox.Checked) getId();等 我正在寻找更好的东西。我不希望我想添加的每个新选项都需要更改UI(例如新复选框)。
我想过从文件中读取可能的选项,但这只会解决UI问题。如何在不使用所有这些值的情况下知道要获得哪些值#34;如果"再次?

2 个答案:

答案 0 :(得分:0)

此任务不需要花哨的设计模式。但是我知道你已经确定了改变的理由(将来添加选项)。因此,您希望最大限度地减少要修改的类的数量。

您真正的问题是如何 创建与其结构将要更改的对象分离。每当更改Person类时,您都不希望您的解析逻辑受到影响。

在以下示例中,CSV对象与它接收和解析的对象真正分离。为了实现这一点,我们编写了一个抽象而不是一个实现。这样我们甚至不会耦合到Person对象,但会欢迎任何实现AttributedObject接口的对象。这种依赖关系被注入我们的CSV解析器。

我在PHP中实现了这个,但想法是一样的。 C#是一种静态语言,因此获取属性会有一些变化。您可以使用某种ArrayAccess接口。

interface AttributedObject {
    public function getAttribute($attribute);
}

class Person implements AttributedObject {

    protected $firstName;
    protected $lastName;
    protected $age;
    protected $IQ;

    public function __construct($firstName, $lastName, $age, $IQ)
    {
        $this->firstName = $firstName;
        $this->lastName = $lastName;
        $this->age = $age;
        $this->IQ = $IQ;
    }

    public function getAttribute($attribute)
    {
        if(property_exists($this, $attribute)) {
            return $this->$attribute;
        }
        throw new \Exception("Invalid attribute");
    }
}

class CSV {

    protected $attributedObject = null;
    protected $attributesToDisplay = null;
    protected $csvRepresentation = null;
    protected $delimiter = null;

    public function __construct(AttributedObject $attributedObject, array $attributesToDisplay, $delimiter = '|')
    {
        $this->attributedObject = $attributedObject;
        $this->attributesToDisplay = $attributesToDisplay;
        $this->delimiter = $delimiter;

        $this->generateCSV();
    }

    protected function generateCSV()
    {
        $tempCSV = null;

        foreach ($this->attributesToDisplay as $attribute) {
            $tempCSV[] = $this->attributedObject->getAttribute($attribute);
        }

        $this->csvRepresentation = $tempCSV;
    }

    public function storeCSV()
    {
        $file = fopen("tmp.csv", "w");
        fputcsv($file, $this->csvRepresentation, $this->delimiter);
    }
}

$person1 = new Person('John', 'Doe', 30, 0);
$csv = new CSV($person1, array('firstName', 'age', 'IQ'));
$csv->storeCSV();

答案 1 :(得分:0)

您可以根据允许用户选择的字段以及所需的字段来构建字段映射集。可以从文件或数据库中读取此数据。您的导入/导出可以根据需要灵活调整。

enter image description here

这是一个可以想象的数据结构,可以保存导入/导出集的信息。

    public class FieldDefinition
    {
        public FieldDataTypeEnum DataType { get; set; }
        public string FieldName{get;set;}
        public int MaxSize { get; set; }
        public bool Required { get; set; }
        public bool AllowNull { get; set; }
        public int FieldIndex { get; set; }
        public bool CompositeKey { get; set; }
    }

    public class BaseImportSet
    {
        private List<FieldDefinition> FieldDefinitions { get; set; }

        protected virtual void PerformImportRecord(Fields selectedfields)
        {
           throw new ConfigurationException("Import set is not properly configured to import record.");
        }

        protected virtual void PerformExportRecord(Fields selectedfields)
        {
           throw new ConfigurationException("Export set is not properly configured to import record.");
        }    

        public LoadFieldDefinitionsFromFile(string filename)
        {
          //Implement reading from file
        }    
    }

    public class UserImportSet : BaseImportSet
    {
        public override void PerformImportRecord(Fields selectedfields)
        {
           //read in data one record at a time based on a loop in base class
        } 

       public override string PerformExportRecord(Fields selectedfields)
        {
           //read out data one record at a time based on a loop in base class
        } 
    }