C# 使用多态性删除基于对象类型的开关调用函数
我有一段代码(如下所示),我希望能够根据传入的对象类型调用函数,我目前有一个switch语句来管理它,但我觉得它有点脏。重构代码以利用多态性来删除switch语句的最佳方法是什么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
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()
时,在函数中确定将调用正确的实现