【问题标题】:Design a data model to flat file transformation... delegates or inheritance?为平面文件转换设计数据模型……委托还是继承?
【发布时间】:2009-08-12 15:16:39
【问题描述】:

我有一个维护应用程序,它必须将企业数据(来自各种数据库/表)转换为平面文件,每个文件都采用特定格式,以供遗留应用程序使用。我有像

这样的数据模型
public class StatusCode
{
    public String Id { get; set; }
    public Char Level { get; set; }
    public String Description { get; set; }
}

我将从数据源中选择一些子集或所有这些记录。而且我需要将每个实体映射到文件的一行,这可能需要调整数据(填充、转换或处理null)。

public delegate String MapEntity<T>(T entity);
public MapEntity<StatusCode> MapStatusCode = delegate(StatusCode entity)
{
    return String.Format("{0},{1},{2}",
        entity.Id.PadLeft(3, '0'),
        entity.Level == 'S' ? 0 : 1,
        entity.Description ?? "-");
}

问题是,如何编写转换类?我是否提供了一个接受映射委托的“DefaultFileCreator”?

public interface IFileCreator
{
    Byte[] Create<T>(MapEntity<T> map, IEnumerable<T> entities);
}

public class DefaultFileCreator : IFileCreator
{
    public Byte[] Create<T>(MapEntity<T> map, IEnumerable<T> entities)
    {
        StringBuilder sb = new StringBuilder();
        foreach (T entity in entities)
            sb.AppendLine(map(entity));

        return Encoding.Default.GetBytes(sb.ToString());
    }
}

...
fileCreator.Create(MapStatusCode, repository<StatusCode>.FindAll());
...

有了这个解决方案,我担心我应该在哪里以及在什么范围内保留映射委托。以及我将如何在不知道T 的情况下给他们打电话(如果我需要的话)。

或者,我是否要更改接口并要求在具体类中进行映射?

public interface IFileCreator<T>
{
    Byte[] Create(IEnumerable<T> entities);
}

public abstract class FileCreator : IFileCreator<T>
{
    protected abstract String Map(T entity);

    public Byte[] Create(IEnumerable<T> entities)
    {
        StringBuilder sb = new StringBuilder();
        foreach (T entity in entities)
            sb.AppendLine(Map(entity));

        return Encoding.Default.GetBytes(sb.ToString());
    }
}

public class StatusCodeFile : FileCreator<StatusCode>
{
    public override String Map(T entity)
    {
        return String.Format("{0},{1},{2}",
            entity.Id.PadLeft(3, '0'),
            entity.Level == 'S' ? 0 : 1,
            entity.Description ?? "-");
    }
}

此解决方案在具体类中爆炸式增长,但它们与映射委托一样薄。我觉得与IFileCreator&lt;T&gt; 和一家工厂一起工作更自在。 (同样,仅在必要时)。

我假设某些基类很有用,因为StringBuilder 循环和Byte[] 编码很简单。具体类是否应该在基类中设置委托属性(而不是调用抽象方法)?我应该在方法上保留类型参数(以及这将如何影响基类/具体类)?

我愿意提供任何解决方案。我的主要目标是易于维护。我现在有 12 个模型/文件,可能会增加到 21 个。我可能需要在任何文件中插入任意页眉/页脚行(这就是为什么我喜欢可覆盖的基类方法 Map)。

【问题讨论】:

    标签: .net inheritance delegates class-design transformation


    【解决方案1】:

    您是否必须为每个可能的映射实际创建具体的子类?也许可以改用 XML 文件(或数据库)来描述每种文件的格式/内容。然后,您有一个类,它采用“FileType”键并使用 XML 中的格式信息来确定如何为该 FileType 构建文件。

    【讨论】:

    • 我认为这与使用映射委托的解决方案(意图)相同。
    • @ajmastrean - 现在我仔细看了一下,你是对的。至于你如何在不知道“T”是什么的情况下做到这一点 - 你只是使用反射来获取所有属性,所以你真的不需要知道对象的类型。
    【解决方案2】:

    现在我已经编写了一些转换,我倾向于使用每个类映射的方法。我必须能够针对伪造的模型运行单元测试,以确保正确构建文件(针对已知的良好示例文件测试它们)。

    我一直将映射委托设为它们所属的“工作流程”类的私有(每个模型/文件一个“工作流程”)。我必须将它们公开以对它们进行单元测试,或输出中间文件内容(工作流将完成的文件保存到数据存储中)。

    每个类的映射似乎更具可测试性和可分解性。

    【讨论】:

    • 我还在考虑覆盖每个具体类 MapEntity(委托)中的抽象属性。与覆盖方法 Map(T) 的效果相同。不同的外观。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多