我们需要实现一个功能来生成巨大的xml文档以导出记录。
我们的情况如下:
所以,我创建了生成Xml的接口
public interface IGenerateXml
{
ResourceIntensiveObject1 Student { get; set; }
ResourceIntensiveObject2 Course { get; set; }
ResourceIntensiveObject3 User { get; set; }
XmlElement Generate();
}
我不想在每个类中声明公共对象。所以,我创建了可用于传递这些对象的基类。并非所有部分都需要访问这些对象,但大多数部分都需要它们。
public class GenerateXmlBase
{
public ResourceIntensiveObject1 Student { get; set; }
public ResourceIntensiveObject2 Course { get; set; }
public ResourceIntensiveObject3 User { get; set; }
}
然后创建类,实现接口并继承基类
public class GenerateSection1 : GenerateXmlBase, IGenerateXml
{
public XmlElement Generate()
{
// some codes to return Xml
return null;
}
}
public class GenerateSection2 : GenerateXmlBase, IGenerateXml
{
public XmlElement Generate()
{
// some codes to return Xml
return null;
}
}
public class GenerateSection3 : GenerateXmlBase, IGenerateXml
{
public XmlElement Generate()
{
// some codes to return Xml
return null;
}
}
通过这种方式,我为每个部分提供了可测试的,易于模拟的类。 但是,当我尝试将所有这些代码组合在一起时,我得到了一些重复的代码,这些代码一次又一次地执行相同的操作(将创建的对象分配给类)。请参阅以下代码:
void GenerateAndSaveXmlDocument()
{
// loading these classes are resource intensive and takes time
// so load only once and pass down to the sub classes
var _student = new ResourceIntensiveObject1();
var _course = new ResourceIntensiveObject2();
var _user = new ResourceIntensiveObject3();
IGenerateXml clsGenerateSection1 = new GenerateSection1();
IGenerateXml clsGenerateSection2 = new GenerateSection2();
IGenerateXml clsGenerateSection3 = new GenerateSection3();
// code goes on for other 9 classes
// <--------- this is where repetitive codes start
clsGenerateSection1.Student = _student;
clsGenerateSection1.Course = _course;
clsGenerateSection1.User = _user;
clsGenerateSection2.Student = _student;
clsGenerateSection2.Course = _course;
clsGenerateSection2.User = _user;
// this one needs only 2 classes
clsGenerateSection3.Student = _student;
clsGenerateSection3.Course = _course;
// and other 9 classes codes which use 2/3 objects
// ........
// generate, combine and save final xml
}
我想知道如何有效地编码以删除那些重复的代码?
P.S:我不想在Generate()
方法中传递这些对象,因为我们不确定生成XML需要多少资源密集型对象。目前,我们只查看了两个部分,未来可能会增长。
答案 0 :(得分:0)
大量重复代码来自属性赋值语句。考虑一个抽象基类GenerateXmlAbstract
,它是GenerateXmlBase
和IGenerateXml
的组合:
public abstract class GenerateXmlAbstract {
public ResourceIntensiveObject1 Student { get; private set; }
public ResourceIntensiveObject2 Course { get; private set; }
public ResourceIntensiveObject3 User { get; private set; }
public GenerateXmlAbstract(
ResourceIntensiveObject1 student,
ResourceIntensiveObject2 course,
ResourceIntensiveObject3 user
) {
Student = student;
Course = course;
User = user;
}
public abstract XmlElement Generate();
}
需要注意的关键是属性赋值语句位于抽象基类构造函数中。这样,可以在继承类中调用构造函数:
public class GenerateSection1 : GenerateXmlAbstract {
public GenerateSection1(
ResourceIntensiveObject1 student,
ResourceIntensiveObject2 course,
ResourceIntensiveObject3 user
) : base(student, course, user) { }
public XmlElement Generate() {
// some codes to return Xml
return null;
}
}
然后可以通过将必要的依赖项传递给构造函数来实例化继承具体类,这也避免了在Generate
方法中传递它们:
void GenerateAndSaveXmlDocument() {
// loading these classes are resource intensive and takes time
// so load only once and pass down to the sub classes
var _student = new ResourceIntensiveObject1();
var _course = new ResourceIntensiveObject2();
var _user = new ResourceIntensiveObject3();
IGenerateXml clsGenerateSection1 = new GenerateSection1(_student, _course, _user);
IGenerateXml clsGenerateSection2 = new GenerateSection2(_student, _course, _user);
IGenerateXml clsGenerateSection3 = new GenerateSection3(_student, _course, _user);
// code goes on for other 9 classes
// generate, combine and save final xml
}
对于不使用所有三个依赖项的类,您可以考虑传递null,在GenerateXmlAbstract
类中定义另一个构造函数,该构造函数接受一个或两个参数或构建更细粒度的继承树,其中并非所有类都包含所有依赖。
答案 1 :(得分:0)
为什么不在循环中分配属性?
var sections = new List <IGenerateXml>()
{
new GenerateSection1(),
new GenerateSection2(),
new GenerateSection3()
}
foreach(var section in sections)
{
section.Student = _student;
section.Course = _course;
section.User = _user;
}