使用多态删除基于对象类型的switch调用函数

时间:2014-11-27 11:54:10

标签: c# reflection refactoring

我有一段代码(如下所示),我希望能够根据传入的对象类型调用函数,我目前有一个switch语句管理这个,但对我来说感觉有点脏。重构代码以利用多态来使我删除switch语句的最佳方法是什么?

if (entity != null)    
{
    //Switch based on entity type
    switch (entity.GetType().Name)
    {

        case "Person":

            //Person implementation

            break;
        case "Organisation":
            //Organisation implementation


            break;
        default:
            break;
    }

}

编辑:为了澄清发现这一点的其他人,我无法访问实体模型来源,这导致我标记答案,如果不是这样,那么我会标记Jon的回答是正确的!

5 个答案:

答案 0 :(得分:2)

要使用多态,您可以在所有实体的基类中引入抽象方法:

public abstract class EntityBase
{
    public abstract void GiveMeABetterName();
}

(我们不知道你要做什么,因此得名......

然后,您将在每个子类(PersonOrganization等)中实施该方法。然后你可以使用:

entity.GiveMeABetterName();

您目前有switch阻止。

现在, 总是一个合适的选项 - 例如,您尝试做的事情可能是您实体域外的事情(例如,在GUI中显示信息) )。如果每个 类型的代码都不属于您的实体,您可以:

  • 使用visitor pattern,如果每个实体有多个操作,这将特别有效。
  • 拥有Dictionary<Type, Action>或类似内容,以查找针对每种类型采取的操作
  • 保留现有方法,但使用isas代替switch,以避免将名称作为字符串文字

答案 1 :(得分:1)

您可以先定义一个界面,为您的实体定义合约。

public interface ISomething
{
    void YourMethod();
}

之后,您可以实施实体PersonOrganization以及推动YourMethod,其中包含您需要的功能。

public class Person : ISomething
{
    public void YourMethod()
    {

    }
}

public class Organization: ISomething
{
    public void YourMethod()
    {

    }  

}

最后,您将在任何需要的地方{/ 1}}传递参考

ISomething

您可以在代码中调用此方法,如下所示:

public void Method(ISomething smth)
        {
            smth.YourMethod();
        }

答案 2 :(得分:0)

我会这样做:

if (entity != null)
{
    if (entity is Person)
    {
        //Person implementation
    }
    else if (entity is Organisation)
    {
        //Organisation implementation
    }
}

答案 3 :(得分:0)

有三种方法可以消除基于switch的调度:

  • PersonOrganization一个公共接口或超类,并提供基于类的实现,
  • PersonOrganization的超类/超级接口中实施Visitor Pattern,或
  • 使用dynamic发送。

当您无法访问PersonOrganization的源代码时,第三种方法可行。实现看起来像这样:

// Add these methods to your class
private void ProcessEntity(Person p) {
    ...
}
// Each overload is specific for one subclass
private void ProcessEntity(Organization o) {
    ...
}

现在你可以这样称呼它:

ProcessEntity((dynamic)entity);

C#将根据entity的运行时类型确定要选择的重载。

答案 4 :(得分:0)

我认为在您的情况下,您应该创建一个接口或一个抽象类,您应该从中继承或实现每个所选类型。

public interface Aggregator{
    void TestFunction();
}

public abstract class Aggregator{
   public abstract void TestFunction();
}

然后您实体的每种可能类型都应该

public class TypeOfYourEntity : Aggregator{
   //implementation of TestFunction
}

然后在您的函数中调用entity.TestFunction()时,您确定将调用正确的实现