如何将公共资源密集型对象传递给子类?

时间:2017-07-29 11:58:44

标签: c# oop inheritance

我们需要实现一个功能来生成巨大的xml文档以导出记录。

我们的情况如下:

  • 某些对象需要加载资源,只能加载 每次迭代一次
  • 团队中的3位开发人员需要划分作品
  • XML文档中有12个重要部分

所以,我创建了生成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需要多少资源密集型对象。目前,我们只查看了两个部分,未来可能会增长。

2 个答案:

答案 0 :(得分:0)

大量重复代码来自属性赋值语句。考虑一个抽象基类GenerateXmlAbstract,它是GenerateXmlBaseIGenerateXml的组合:

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;
}