我遇到的情况是我有一个IEnumerable,我需要对其进行迭代并针对每个项目执行一些代码。

要执行的代码取决于项的实际类型,而我正在寻找的是一种没有任何条件的好方法,因此,如果我需要处理的派生类型数量增加,我只需要编写一个新的处理程序,而不更改任何现有代码。

为了说明这一点,我有一个示例,其中第三方库包含以下代码:

public abstract class BaseObject{    }

public class Derived1: BaseObject { }

public class Derived2 : BaseObject { }


我的本地代码执行类似以下操作:

void Execute(IEnumerable<BaseObject> list)
{
    foreach (var item in list)
        item.DoWork();
}


我尝试创建扩展方法来做到这一点:

public static class Extensions
{
    public static int DoWork(this BaseObject obj) { return 0; }

    public static int DoWork(this Derived1 obj) { return 1; }

    public static int DoWork(this Derived2 obj) { return 2; }
}


这显然不起作用,因为枚举中的每个项目都是BaseObject类型的,因此始终调用返回0的扩展方法。

我可以选择为每个实现接口的每个派生类型创建一个新的派生类型:

public class MyDerived1: Derived1, IMyInterface
{
    public int DoWork(){return 1;}
}

public class MyDerived2: Derived2, IMyInterface
{
    public int DoWork(){return 2;}
}

public interface IMyInterface
{
    int DoWork();
}


然后我可以迭代并投射到新接口:

void Execute(IEnumerable<BaseObject> list)
{
    foreach (var item in list)
    {
       var local = item as IMyInterface;
       local?.DoWork();
    }
}


但这需要构造我的派生类型,而关于构造哪种类型的决定仍然需要条件语句,对于添加的任何新类型,该条件语句都需要更改。

显然,这里使用了工厂模式,这是我到目前为止提供的最干净的解决方案。

命令模式提供了一种解决方案,但是由于要执行的命令取决于派生类型的类型,因此仍然需要条件来构造此命令...

谁能建议一种方法,当将新的派生类型添加到组合中时,该方法将完全消除所有需要更改的条件?

最佳答案

您可以使用dynamic。通常我不喜欢它,但是在这种情况下,这似乎是一个不错的选择。

public static class Worker
{
    public static int DoWork(BaseObject obj) { return 0; }
    public static int DoWork(Derived1 obj) { return 1; }
    public static int DoWork(Derived2 obj) { return 2; }
}

void Execute(IEnumerable<BaseObject> list) {
    foreach (dynamic item in list) {
        Worker.DoWork(item);   // Method resolution done at run-time
    }
}

关于c# - 第三方类的多态扩展,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36354522/

10-12 12:45
查看更多