在编写具有相同数据结构的不同对象时避免重复

时间:2014-07-08 14:12:30

标签: c#

在我目前的系统中,我有两个具有几乎相同的属性集的EF对象,但由于各种原因,它们可以统一或加入以共享一些相同的结构。它实际上是个人细节,所以看起来有点像这样:

public partial class Person
{
    public int PersonID { get; set; }
    public string Title { get; set; }
    public string Surname { get; set; }
    public string AddressLine1 { get; set; }
    public string AddressLine2 { get; set; }
    // .. etc
}

public partial class Member
{
    public int MemberID { get; set; }
    public string Title { get; set; }
    public string Surname { get; set; }
    public string AddressLine1 { get; set; }
    public string AddressLine2 { get; set; }
    // .. etc
}

最终必须将这两种对象类型的混合写入同一文件,如下所示:

foreach (Person p in People)
{
    StringBuilder lineBuilder = new StringBuilder();
    lineBuilder.Append("\"");
    lineBuilder.Append(p.PersonID.ToString());
    lineBuilder.Append("\",\"");
    lineBuilder.Append(p.Title);
    lineBuilder.Append("\",\"");
    lineBuilder.Append(p.Forename);
    lineBuilder.Append("\",\"");
    // etc...
}

foreach (Member m in Members)
{
    StringBuilder lineBuilder = new StringBuilder();
    lineBuilder.Append("\"");
    lineBuilder.Append(m.MemberID.ToString());
    lineBuilder.Append("\",\"");
    lineBuilder.Append(m.Title);
    lineBuilder.Append("\",\"");
    lineBuilder.Append(m.Forename);
    lineBuilder.Append("\",\"");
    // etc...
}

这显然是一件坏事 - 它不仅重复代码,而且它依赖于两个循环,在输出中保持相同的列数,如果代码被更改,可能很容易被忽略。

没有创建一个中间对象并将字段映射到它 - 这实际上只是将问题转移到其他地方 - 是否有办法解决这个问题,这使我可以将其转化为单个循环?

5 个答案:

答案 0 :(得分:4)

在两个实体上放置一个接口,让你的逻辑对接口而不是具体的类

答案 1 :(得分:1)

假设你因为使用DB first EF而陷入这两个实体,我可以想到三个建议:

  1. 使用AutoMapper将这两个对象映射到第三个类。在第三类中覆盖ToString()。如果您包含AutoMapper单元测试以验证映射,则您永远不必担心更改 - AutoMapper将选择它并且无法通过测试。

  2. 将数据库重构为具有“人员类型”字段的多态Person表,然后您只有一个具有人员类型字段的Person实体。

  3. 首先使用代码EF并拥有基础人员类或界面。

答案 2 :(得分:1)

你在这里做了两件事。您在引号中包装字段,并且您使用逗号连接一系列字符串。只需编写一个方法,为任意数量的任意字符串执行此操作:

public static string BuildLine(IEnumerable<string> fields)
{
    return string.Join(",", fields.Select(WrapInQuotes));

}
private static string WrapInQuotes(string rawData)
{
    return string.Format("\"{0}\"", rawData);
}

一旦你有了这个,你现在可以让你的每个类只提供他们的字段的集合,而不负责格式化它们的输出。

请注意,您似乎在此处写出了CSV文件。我的第一个建议是不要。只需使用现有的CSV编写器,即可以为您处理所有字符转义等等,这样您就不必这样做了。到目前为止,您还有一些事情尚未解决,包括其中包含换行符或引号的字段,或者您实际上不应引用转义每个字段的事实,而只是那些包含需要引用转义的字符(即换行符,如果你想支持多行字段或逗号)。

答案 3 :(得分:0)

为它创建一个接口(或抽象类)。

public interface IDetails
{
    string Title;
    string Surname;
    string AddressLine1;
    string AddressLine2;
}

public partial class Member : IDetails
{
    //etc
}

public partial class Person : IDetails
{
    //etc
}

答案 4 :(得分:0)

你可以使用界面,

public interface ISocialHuman{
    public int PersonID { get; set; }
    public string Title { get; set; }
    public string Surname { get; set; }
    public string AddressLine1 { get; set; }
    public string AddressLine2 { get; set; }
}

public static void writeHumanSomewhere(ISocialHuman){
    StringBuilder lineBuilder = new StringBuilder();
    lineBuilder.Append("\"");
    lineBuilder.Append(p.PersonID);
    lineBuilder.Append("\",\"");
    lineBuilder.Append(p.Title);
    lineBuilder.Append("\",\"");
    lineBuilder.Append(p.Forename);
    lineBuilder.Append("\",\"");
}

但您应该更改ID名称。