首页 > 解决方案 > 在抽象基类的静态方法中实例化多个派生类中的任何一个(取决于参数)

问题描述

我一直在尝试找到一种优雅的方法来避免在所有派生类中重复代码。在这一点上,我不确定进行的最佳方式。

我想在基类中编写一个方法,该方法将实例化并使用其任何派生类,而无需在编写新派生类时编辑该方法。

我曾尝试学习/使用通用方法,但开始认为我可能会为这个应用程序走向死胡同。我知道使用反射可能会很昂贵,而且由于这种方法旨在处理数百甚至数千个元素,所以这似乎是个坏主意。

现在我正在考虑尝试以某种方式将课程本身作为参数传递......也许。这对我来说似乎也不对。

我愿意做这项研究,但希望能有任何帮助为我指明正确的方向。

这是我所拥有的内容的精简版...

基类:

public abstract class Element
{
    public string ElementName { get; }
    public List<string> BadParameters { get; set; } = new List<string>();

    //Constructor
    public Element(string name)
    {
        ElementName = name;
    }

    //The method in question---
    public static List<string> GetBadParameters(//derived class to instantiate)
    {
        var elem = new //derived class();
        return elem.BadParameters;
    }

}

派生类 1:

public class Wall : Element
{
    public double Length { get; set; }
    public bool LoadBearing { get; set; }

    //Constructor
    public Wall(string name): base(name)
    {
        SetBadParameters();
    }

    public void SetBadParameters()
    {
        BadParameters = //A wall specific way of setting bad parameters
    }
}

派生类 2:

public class Floor : Element
{
    public double Area { get; set; }
    public double Slope { get; set; }

    //Constructor
    public Floor(string name): base(name)
    {
        SetBadParameters();
    }

    public void SetBadParameters()
    {
        BadParameters = //A floor specific way of setting bad parameters
    }
}

执行:

public class Implementation
{
    public List<string> GetAllBadElementParameters()
    {
        List<string> output = new List<string>;

        List<string> badWalls = GetBadParameters(//Wall class)
        List<string> badFloors = GetBadParameters(//Floor class)

        output = output.AddRange(badWalls).AddRange(badFloors);
        return output;
    }
}

编辑 - 澄清:

的实际内容

public List<string> BadParameters

不要紧。糟糕的参数,它们如何以及为什么不好,都是无关紧要的。

我想要完成的是避免在派生类中定义方法“GetBadParameters()”,因为该方法对于所有派生类都是完全相同的。

只有“BadParameter”基类属性的填充会从一个派生类更改为另一个派生类。

编辑 2 - 我尝试在基类中使用通用方法:

我知道这行不通,但它可能会传达我想要发生的事情。

    public static List<string> GetAllBadParameters<T>(List<string> names) where T : ANY DERIVED CLASS, new()
    {
        List<string> output = new List<string>();

        foreach (string name in names)
        {
            var elem = new T(name);
            foreach (string badParameter in elem.BadParameters)
            { 
                output.Add(badParameter); 
            }
        }

        return output;
    }

标签: c#instantiationdryderived-classbase-class

解决方案


我假设您的 BadParameter 列表内容对于所有派生类都是相同的。如果这个列表不常见,那么在基类中填写这些列表是没有意义的。根据这个假设,我可以建议您进行以下更改。

您的基类看起来像这样。无需将 GetBadParameters() 设为静态

public abstract class Element
    {
        public string ElementName { get; }
        public List<string> BadParameters { get; set; } = new List<string>();

        //Constructor
        public Element(string name)
        {
            ElementName = name;
        }

        /// <summary>
        /// Tjis Method is common for alal derived classes. Assuming content is same for all dervied class
        /// </summary>
        /// <returns></returns>
        //The method in question---
        public List<string> GetBadParameters()
        {
            return new List<string>() { "1", "2" };
        }

    }

您的第一个派生类 Wall,它将从 base 调用 GetBadParameters。

 public class Wall : Element
    {
        public double Length { get; set; }
        public bool LoadBearing { get; set; }

        //Constructor
        public Wall(string name) : base(name)
        {
            SetBadParameters();
        }

        public void SetBadParameters()
        {
            BadParameters = GetBadParameters();//Calling base GetBadParameters
        }
    }

第二个派生类“Floor”也是如此

 public class Floor : Element
    {
        public double Area { get; set; }
        public double Slope { get; set; }

        //Constructor
        public Floor(string name) : base(name)
        {
            SetBadParameters();
        }

        public void SetBadParameters()
        {
            BadParameters = GetBadParameters();//Calling base GetBadParameters
        }
    }

在您的实现类中,您可以通过将 Element 类作为参考并调用相应的 GetBadParameters 来创建墙壁和地板对象

public class Implementation
    {
        public List<string> GetAllBadElements()
        {
            List<string> output = new List<string>;

            Element _wall = new Wall("wall");
            Element _floor = new Floor("floor");
            List<string> badWalls = _wall.GetBadParameters(); //Returns Wall bad Parameters
            List<string> badFloors = _floor.GetBadParameters(); //Returns Floor bad Parameters

            output = output.AddRange(badWalls).AddRange(badFloors);
            return output;
        }
    }

推荐阅读