C#-在我没有看到的类中使用多态性';不写

C#-在我没有看到的类中使用多态性';不写,c#,architecture,inheritance,polymorphism,C#,Architecture,Inheritance,Polymorphism,在我无法修改的类中实现多态行为的最佳方法是什么?我目前有一些代码,如: if(obj is ClassA) { // ... } else if(obj is ClassB) { // ... } else if ... 显而易见的答案是向基类添加虚拟方法,但不幸的是,代码位于不同的程序集中,我无法修改它。有没有比上面丑陋而缓慢的代码更好的方法来处理这个问题?查看模式。这使您几乎可以在不更改类的情况下向类添加虚拟方法。如果使用的基类没有Visit方法,则需要使用带有动态强制转换

在我无法修改的类中实现多态行为的最佳方法是什么?我目前有一些代码,如:

if(obj is ClassA) {
    // ...
} else if(obj is ClassB) {
    // ...
} else if ...
显而易见的答案是向基类添加虚拟方法,但不幸的是,代码位于不同的程序集中,我无法修改它。有没有比上面丑陋而缓慢的代码更好的方法来处理这个问题?

查看模式。这使您几乎可以在不更改类的情况下向类添加虚拟方法。如果使用的基类没有Visit方法,则需要使用带有动态强制转换的扩展方法。下面是一些示例代码:

public class Main
{
    public static void Example()
    {
        Base a = new GirlChild();
        var v = new Visitor();
        a.Visit(v);
    }
}

static class Ext
{
    public static void Visit(this object b, Visitor v)
    {
        ((dynamic)v).Visit((dynamic)b);
    }
}

public class Visitor
{
    public void Visit(Base b)
    {
        throw new NotImplementedException();
    }

    public void Visit(BoyChild b)
    {
        Console.WriteLine("It's a boy!");
    }

    public void Visit(GirlChild g)
    {
        Console.WriteLine("It's a girl!");            
    }
}
//Below this line are the classes you don't have to change.
public class Base
{
}

public class BoyChild : Base
{
}

public class GirlChild : Base
{
}

嗯。。。似乎更适合我


看起来好像有很多代码,但它会使客户机代码更接近您想要的。此外,它还可以让您思考实际使用的接口。

我想说的是,这里的标准方法是将要“继承”的类包装为受保护的实例变量,然后在容器类中模拟包装类的所有非私有成员(方法/属性/事件等)。然后可以将该类及其相应的成员标记为虚拟,以便使用标准多态性特性

这里有一个例子来说明我的意思
ClosedClass
是程序集中包含的类,您无权访问该类的代码

public virtual class WrapperClass : IClosedClassInterface1, IClosedClassInterface2
{
    protected ClosedClass object;

    public ClosedClass()
    {
        object = new ClosedClass();
    }

    public void Method1()
    {
        object.Method1();
    }

    public void Method2()
    {
        object.Method2();
    }
}
如果您引用的任何程序集都设计得很好,那么您可能想要访问的所有类型/成员都将被适当地标记(抽象、虚拟、密封),但事实上不幸的是,情况并非如此(有时您甚至会在基类库中遇到此问题)。在我看来,包装器类是解决这个问题的方法。它确实有它的好处(即使您要从中派生的类是可继承的),即删除/更改您不希望类的用户访问的方法的修饰符。BCL中的
ReadOnlyCollection
就是一个很好的例子。

提供了一种向现有类添加额外方法签名的简单方法。这需要3.5框架

创建一个静态实用程序类并添加如下内容:

public static void DoSomething(this ClassA obj, int param1, string param2)
{
    //do something
}
在页面上添加对实用程序类的引用,此方法将显示为ClassA的成员。您可以通过这种方式重载现有方法或创建新方法。

查看模式。诺多林实际上解释了它,但没有给出图案的名称


Decorator是在不继承的情况下扩展行为的方法。在Noldorin的代码中,我唯一要改变的是,构造函数应该接收您正在装饰的对象的实例。

真的吗?怎么用?zildjohn试图适应的另一个接口是什么。。。?Visitor非常适合。这在功能上与harpo提到的适配器模式相同。是的,我在他编辑他的文章以包含代码示例后意识到了这一点。啊,好吧,我猜他原来的帖子比我快…在读了维基百科之后,看起来我需要给每个类添加一个回调方法,但我不能修改这些类。我读错了吗?这并没有给出动态调度。你真的了解访问者模式是如何工作的吗?我喜欢它。不幸的是,我被困在.NET2.0上。但这是你的一票,无论如何,我认为你没有抓住重点--扩展方法不能是虚拟的。虚拟方法不是重点--多态行为是,实现这一点有不同的方法。显然,使用虚拟方法的派生类将是“正确”的方法,但扩展方法将是一种快速而肮脏的选择,这取决于您需要完成什么。是的,多态行为是关键,扩展方法无助于实现这一点。重载不会为您提供多态性所需的动态调度。如果您只有几个if语句,那么重构可能是一种过火的行为。有时候你不必感到快乐;)
public static void DoSomething(this ClassA obj, int param1, string param2)
{
    //do something
}