如何制作2个不兼容的类型,但具有相同的成员,可以互换?

Jac*_*sch 4 .net c# design-patterns

昨天我们团队中的2个人带着一个不寻常的问题来找我.我们在其中一个winforms应用程序中使用了第三方组件.所有代码都已针对它编写.然后,他们希望将同一供应商的另一个第三方组件合并到我们的应用程序中.令他们高兴的是,他们发现第二部分与第一部分具有完全相同的公共成员.但令他们沮丧的是,这两个组件具有完全独立的继承层次结构,并且没有实现通用接口.让你好奇......好吧,让我好奇.

问题的一个例子:

不兼容的类型http://www.freeimagehosting.net/uploads/f9f6b862f1.png

public class ThirdPartyClass1
{
    public string Name
    {
        get
        {
            return "ThirdPartyClass1";
        }
    }

    public void DoThirdPartyStuff ()
    {
        Console.WriteLine ("ThirdPartyClass1 is doing its thing.");
    }
}

public class ThirdPartyClass2
{
    public string Name
    {
        get
        {
            return "ThirdPartyClass2";
        }
    }

    public void DoThirdPartyStuff ()
    {
        Console.WriteLine ("ThirdPartyClass2 is doing its thing.");
    }
}
Run Code Online (Sandbox Code Playgroud)

很高兴他们觉得复制和粘贴他们为第一个组件编写的代码并不是正确的答案.因此,他们考虑将组件即时分配到对象引用中,然后在检查它是什么类型之后修改代码以执行条件转换.但这可能比复制和粘贴方法更加丑陋.

然后他们问我是否可以编写一些反射代码来访问属性并从两种不同的对象类型调用方法,因为我们知道它们是什么,并且它们完全相同.但我的第一个想法是,优雅.我认为必须有一个更好,更优雅的解决方案来解决这个问题.

Jac*_*sch 12

我的第一个问题是,2个第三方组件类是否已密封?它们不是.至少我们有这个.

因此,由于它们没有密封,因此可以通过以下方式解决问题:

从2个第三方类的重合成员中提取公共接口.我叫它Icommon.

public interface ICommon
{
    string Name
    {
        get;
    }

    void DoThirdPartyStuff ();
}
Run Code Online (Sandbox Code Playgroud)

然后创建2个新类; DerivedClass1和DerivedClass2分别从ThirdPartyClass1和ThirdPartyClass2继承.这两个新类都实现了ICommon接口,但完全是空的.

public class DerivedClass1
    : ThirdPartyClass1, ICommon
{
}

public class DerivedClass2
    : ThirdPartyClass2, ICommon
{
}
Run Code Online (Sandbox Code Playgroud)

现在,即使派生类是空的,接口也会被基类所满足,这是我们从一开始就从中提取接口的地方.生成的类图如下所示.

alt text http://www.freeimagehosting.net/uploads/988cadf318.png

所以现在,而不是我们以前的:

ThirdPartyClass1 c1 = new ThirdPartyClass1 ();
c1. DoThirdPartyStuff ();
Run Code Online (Sandbox Code Playgroud)

我们现在可以这样做:

ICommon common = new DerivedClass1 ();
common. DoThirdPartyStuff ();
Run Code Online (Sandbox Code Playgroud)

DerivedClass2也是如此.

其结果是,所引用ThirdPartyClass1的一个实例,我们现有的代码可以作为留给,由刚换出了ICommon参考ThirdPartyClass1参考.然后,将参考ICommon可以给予DerivedClass1或DerivedClass2,这当然反过来从ThirdPartyClass1和ThirdPartyClass2分别继承的一个实例.一切正常.

我不知道是否有特定的名称,但对我来说它看起来像是适配器模式的变体.

也许我们可以用C#4.0中的动态类型来解决问题,但是这样做没有编译时检查的好处.

我很想知道是否有其他人有另一种优雅的方法来解决这个问题.