Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/email/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 设计一个数据模型到平面文件转换。。。委托还是继承?_.net_Inheritance_Delegates_Class Design_Transformation - Fatal编程技术网

.net 设计一个数据模型到平面文件转换。。。委托还是继承?

.net 设计一个数据模型到平面文件转换。。。委托还是继承?,.net,inheritance,delegates,class-design,transformation,.net,Inheritance,Delegates,Class Design,Transformation,我有一个维护应用程序,它必须将企业数据(来自各种数据库/表)转换为平面文件,每个文件都具有特定的格式,供遗留应用程序使用。我有这样的数据模型 public class StatusCode { public String Id { get; set; } public Char Level { get; set; } public String Description { get; set; } } 我将从数据源中选择这些记录的一些子集或全部。我需要将每个实体映射到文件

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

public class StatusCode
{
    public String Id { get; set; }
    public Char Level { get; set; }
    public String Description { get; set; }
}
我将从数据源中选择这些记录的一些子集或全部。我需要将每个实体映射到文件的一行,这可能需要调整数据(填充、转换或处理
null

此解决方案在具体类中爆炸,但它们与映射委托一样薄。而且我觉得与IFileCreator和工厂一起工作更舒服。(同样,仅在必要时)

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


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

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

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

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


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

我认为这与使用映射委托是相同的解决方案。@ajmastrean-现在我更仔细地看了一下,你是对的。至于如何在不知道“T”是什么的情况下实现这一点,您只需要使用反射来获取所有属性,因此您实际上不需要知道对象的类型。我还考虑在每个具体类中重写抽象属性MapEntity(delegate)。与重写方法映射(T)的效果相同。不同的外观。
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 ?? "-");
}
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());
...
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 ?? "-");
    }
}