2017-02-28 11 views
1

项目类型:C#类库从ASP.NET应用程序 Framework版本被称为:4.5.1分部类,以避免实例化多个类相同的文件创建的字符串

我一直在寻找各地关于偏类和所有我发现的参考是他们是代码气味,但我发现他们都在谈论上帝类,这不是。我需要帮助来决定这种情况下最好的方法。

我知道部分类通常是设计器生成的代码,但...我不能决定下面列出的选项。我的选择2与部分类是一个非常糟糕的主意吗?

我正在写一个程序来创建非典型的CSV文件,这意味着该文件不包含柱状数据。每行包含不同的数据和不同数量的列。

无论使用哪种方法,都需要访问两个数据集和一个Document类,该类包含public List<string>,其中每个方法都将一行(字符串)添加到。

我所知道的:

  • 每一行都有一个非唯一类型标识符,如 “H00”, “H10”, “D50”, “D55” ......

  • 每行根据行类型标识符具有固定的列数 某些行与其他行相关,而其他行则不与其他行相关。

  • 大约有25个(给定或取5个)类型的行,因此将有大约25个文件部分类的一部分加上一个构造函数。这个数字可能会增长,但绝对不会超过40个。

我不想要什么:

  • 一个大类为每个行类型的方法。

  • 一大帮助方法的大方法。

选项1:为每种线类型创建一个单独的类。

选项1问题:这会创建大量的类实例。

选项2:为包含与正在创建的线型相匹配的方法的每个线型创建一个名为“Line”的分部类,并带有单独的* .cs文件。在这个例子中,我想我会在构造函数中使用初始化数据集和文档的类级属性。

选项2:部分类被认为是代码异味,因为它们难以管理并使代码更复杂。

典型方法中,省略了参数,以保持该示例中简单:选择

public class Document 
{ 
    //The document class would not be part of the partial class 
    //The document has other properties, I left them out to keep it simple 
    public List<string> Lines { get; set; } 

    public Document() 
    { 
     this.Lines = new List<string> 
    } 
} 

partial class LineMethods // file named: H01.cs 
{ 
    public void H01(DataSet ds1, DataSet ds2, Document doc) 
    { 

     string[] fields = new string[3]; 
     fields[0] = "855"; 
     fields[1] = "value from datatable"; 
     fields[2] = "value from datatable"; 

     string line = string.Join(",", fields); 
     doc.Lines.Add(line); 
    } 
} 

partial class LineMethods // File named: H10 
{ 
    public void H10(DataSet ds1, DataSet ds2, Document doc) 
    { 
     string[] fields = new string[27]; 
     fields[0] = "855"; 
     fields[10] = "other from datatable"; 
     fields[16] = "other data"; 

     //Line variable would be added to the "document.Lines.Add" 
     string line = string.Join(",", fields); 
     doc.Lines.Add(line); 
    } 
} 

EDIT回答后: @Hristo,每一行需要执行为每个文件和一些方法将需要不同的参数。每条生产线的要求都会改变。

关于是否需要一行的决定取决于其中一个数据集中的数据。例如,当我创建发票时,如果发票没有折扣,那么我不会为折扣创建折扣,或者如果订单有运费,则会确定是否会写入运费的折扣。如果在创建该行的方法中确定了这个逻辑,我认为编写和维护会是最容易的。如果不需要该行,则将返回零长度,并且该行将不会被添加到Doc.Lines

回答

3

您应该问自己,从长远来看什么是最容易管理的。什么是最容易阅读和维护的。

解决方案1:

我会走这条路:

public class Document 
{ 
    //The document class would not be part of the partial class 
    //The document has other properties, I left them out to keep it simple 
    public List<string> Lines { get; set; } 

    public Document() 
    { 
     this.Lines = new List<string> 
    } 
} 

public interface ILine 
{ 
    string[] ProduceLine(DataSet ds1, DataSet ds2); 
} 

public class H01 : ILine 
{ 
    public string[] ProduceLine(DataSet ds1, DataSet ds2) 
    { 
     string[] fields = new string[3]; 
     fields[0] = "855"; 
     fields[1] = "value from datatable"; 
     fields[2] = "value from datatable"; 

     return fields; 
    } 
} 

public class H10 : ILine 
{ 
    public string ProduceLine(DataSet ds1, DataSet ds2) 
    { 
     string[] fields = new string[27]; 
     fields[0] = "855"; 
     fields[10] = "other from datatable"; 
     fields[16] = "other data"; 

     return fields; 
    } 
} 

var doc = new Document(); 

foreach (ILine line in lines) 
{ 
    doc.Lines.Add(string.Join(",", line.ProduceLine(ds1, ds2))); 
} 

编辑(哪里来lines从):

嗯,真的取决于你。最简单的例子:

var lines = new List<ILine>(new [] 
{ 
    new H10(), 
    new H01() 
}); 

它将如果你没有了解每一个实施和根本还统一注入所有的人都在你的构造更好。但这真的取决于你的商业案例。你如何确定使用哪个实现?在所有情况下你需要全部吗?等

如:

public class MyWorker 
{ 
    // This would require that you setup Inversion of Control container and use it to resolve MyWorker. 
    // See: http://stackoverflow.com/questions/1961549/resolving-ienumerablet-with-unity 
    public MyWorker(IEnumerable<ILine> lines) 
    { 
    this.lines = lines; 
    } 
} 

解决方案2:

或者,如果你真的喜欢你的部分结构,你可以使用委托像这样:

delegate string[] ProduceLine(DataSet ds1, DataSet ds2); 

partial class LineMethods // file named: H01.cs 
{ 
    public string[] H01(DataSet ds1, DataSet ds2) 
    { 
     string[] fields = new string[3]; 
     fields[0] = "855"; 
     fields[1] = "value from datatable"; 
     fields[2] = "value from datatable"; 

     return fields; 
    } 
} 

partial class LineMethods // File named: H10 
{ 
    public string[] H10(DataSet ds1, DataSet ds2) 
    { 
     string[] fields = new string[27]; 
     fields[0] = "855"; 
     fields[10] = "other from datatable"; 
     fields[16] = "other data"; 

     return fields; 
    } 
} 

var h01Method = new ProduceLine(LineMethods.H01); 
doc.Lines.Add(string.Join(",", h01Method.Invoke(ds1, ds2)); 

你决定什么更容易阅读和维护。

+1

我正要写同样的答案。我不明白为什么OP与选项1相反。最多只有40个文件类型,因此最多有40个对象 - 担心这会导致过早优化。选项2意味着LineMethod类的消费者需要了解所有部分类中的每种方法,这可能会成为维护的噩梦。 –

+0

我并不反对任何事情,我只是在困难的时候决定。 – Moses

+0

Hristo,谢谢你的回复,我喜欢你的第一个答案,使用界面。虽然我对foreach的实现有点困惑(线条上的ILine)。我不知道线路来自哪里。 – Moses

相关问题