C# 使用多态性删除基于对象类型的开关调用函数

C# 使用多态性删除基于对象类型的开关调用函数,c#,reflection,refactoring,C#,Reflection,Refactoring,我有一段代码(如下所示),我希望能够根据传入的对象类型调用函数,我目前有一个switch语句来管理它,但我觉得它有点脏。重构代码以利用多态性来删除switch语句的最佳方法是什么 if (entity != null) { //Switch based on entity type switch (entity.GetType().Name) { case "Person": //Person implementatio

我有一段代码(如下所示),我希望能够根据传入的对象类型调用函数,我目前有一个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的答案标记为正确

我会这样做:

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

您可以从定义一个接口开始,该接口将为您的实体定义一个契约

public interface ISomething
{
    void YourMethod();
}
在此之后,您可以实施您的实体
Person
Organization
以及推进
YourMethod
,这将包含您需要的功能

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

    }
}

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

    }  

}
最后,您将在任何需要的地方传递对
ISomething
的引用

public void Method(ISomething smth)
        {
            smth.YourMethod();
        }
您可以在代码中调用此方法,如下所示:

var person = new Person();
var org = new Organization();


Method(person); // will call implementation of person
Method(org) //will call implementation of organization

要使用多态性,您需要在所有实体的基类中引入一个抽象方法:

public abstract class EntityBase
{
    public abstract void GiveMeABetterName();
}
(我们不知道你想做什么,因此得名

然后在每个子类(
Person
Organization
等)中实现该方法

entity.GiveMeABetterName();
您当前拥有
开关的位置

现在,这并不总是一个合适的选项-例如,您尝试执行的操作可能超出了实体的域(例如,在GUI中显示信息)。如果这些类型的代码确实不属于您的实体,您可以:

  • 使用,如果每个实体都有多个操作,这将非常有效
  • 有一本
    字典
    或类似的东西来查找每种类型的操作
  • 保留现有方法,但使用
    is
    as
    而不是
    switch
    以避免将名称作为字符串文本

    • 这里有三种方法可以消除基于
      开关的调度:

      • 人员
        组织
        提供公共接口或超类,并提供基于类的实现
      • 人员
        组织
        的超类/上级界面中实施,或
      • 使用
        dynamic
        dispatch
      第三种方法在您无法访问
      个人
      组织
      的源代码时有效。实现如下所示:

      // 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);
      
      现在你可以这样称呼它:

      // 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#将根据
      实体的运行时类型

      确定要选择哪些重载。我认为在您的情况下,您应该创建一个接口或一个抽象类,您选择的每个类型都应该从中继承或实现

      public interface Aggregator{
          void TestFunction();
      }
      

      那么您的实体的每种可能类型都应该具有

      public class TypeOfYourEntity : Aggregator{
         //implementation of TestFunction
      }
      
      然后在调用
      entity.TestFunction()
      时,在函数中确定将调用正确的实现