如何使两种不兼容的类型,但具有相同的成员,可以互换?

2023-12-07

昨天,我们团队中的两个人来找我,提出了一个不常见的问题。我们正在我们的 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.");
    }
}

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

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


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

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

从 2 个第三方类的重合成员中提取一个公共接口。我把它称为“Icommon”。

public interface ICommon
{
    string Name
    {
        get;
    }

    void DoThirdPartyStuff ();
}

然后创建2个新类; DerivedClass1 和 DerivedClass2 分别继承自 ThirdPartyClass1 和 ThirdPartyClass2。这两个新类都实现了 ICommon 接口,但在其他方面都是空的。

public class DerivedClass1
    : ThirdPartyClass1, ICommon
{
}

public class DerivedClass2
    : ThirdPartyClass2, ICommon
{
}

现在,即使派生类是空的,基类也满足接口,这是我们首先从中提取接口的地方。 生成的类图如下所示。

替代文本 http://www.freeimagehosting.net/uploads/988cadf318.png

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

ThirdPartyClass1 c1 = new ThirdPartyClass1 ();
c1. DoThirdPartyStuff ();

我们现在可以这样做:

ICommon common = new DerivedClass1 ();
common. DoThirdPartyStuff ();

对于 DerivedClass2 也可以完成同样的操作。

结果是,我们所有引用 ThirdPartyClass1 实例的现有代码都可以保留原样,只需将 ThirdPartyClass1 引用替换为 ICommon 引用即可。然后,可以为 ICommon 引用提供 DerivedClass1 或 DerivedClass2 的实例,当然,它们又分别继承自 ThirdPartyClass1 和 ThirdPartyClass2。一切都正常。

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

也许我们可以使用 C# 4.0 中的动态类型来解决问题,但这不会带来编译时检查的好处。

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使两种不兼容的类型,但具有相同的成员,可以互换? 的相关文章

随机推荐

  • Pandas 左合并将数据保留在重复列的右数据框中

    我想合并两个数据框 df2 可能有更多列 并且始终为 1 行 我希望 df2 行中的数据覆盖 df 中的匹配行 笔记 ser and no列组合在一起使行独一无二 import pandas as pd df pd DataFrame se
  • 如何使用 sed 删除文件的最后 n 行

    我想删除一些n从文件末尾开始的行 这可以使用 sed 来完成吗 例如 要删除第 2 行到第 4 行 我可以使用 sed 2 4d file 但我不知道行号 我可以使用删除最后一行 sed d file 但我想知道删除的方法n从末尾开始的行
  • QCustomPlot 小部件上类似工具提示的方块

    我在 Qt Creator 中使用 QCustomPlot 我还没有为我的小部件或任何东西指定任何工具提示 当我将光标按住绘图上而不移动时 会出现一个类似工具提示的空东西 我想知道如何关闭它 我很感谢有关此事的任何提示 感谢大家的帮助 在
  • 异步等待后获取 Promise 数组

    i m trying to create an array of the daily forecast mapping over an array with cities I m trying to map over the array o
  • 如何告诉 BeautifulSoup 将特定标签的内容提取为文本? (不碰它)

    我需要解析一个包含 code 标签的html文档 我得到这样的代码块 soup BeautifulSoup str content code blocks soup findAll code 问题是 如果我有这样的代码标签 code cla
  • 无法通过HttpWebRequest获取HTML代码

    我正在尝试解析页面的 HTML 代码http odds bestbetting com horse racing today为了获得比赛列表等 问题是我无法检索该页面的 HTML 代码 下面是该函数的 C 代码 public static
  • Cron 作业 stderr 到电子邮件和日志文件?

    我有一个 cron 工作 SP s StartDailyS1 sh gt LP s MirrorLogS1 txt Where SP s是脚本的路径 LP s是日志文件的路径 这会将 stdout 发送到日志文件 并将 stderr 发送到
  • 使用 R 使用另一个数据框中的值插入缺失数据的值

    All 我有一个问题 我担心在这里问可能太平庸 但在其他地方寻找它会让我误入歧途 我可能没有使用正确的搜索词 我在 R 中有一个面板数据框 国家 地区 年份 给定变量上有一些缺失值 我试图用另一个数据框中另一个向量的值来估算它们 这是我正在
  • 如何在没有嵌套滚动视图的情况下实现新材料 Gmail 工具栏?

    我想实现新的 gmail 之类的工具栏 没有嵌套滚动视图 它可以滚动 但向下滚动时背景应该可见 It will look like this 这不是一个嵌套的滚动视图 它回收者视图 如果你想要这样的搜索栏 你可以使用CardView和 Ed
  • 用文本填充画布形状

    我想弄清楚如何将文本添加到画布形状 例如这是我的Code var text 5 text to display over the circle context fillStyle red context beginPath context
  • 将文本放在字体很棒的图标上方?

    如何在 font Awesome 图标上方水平和垂直居中文本 示例代码 div i class icon circle i span text span div 只需将 display table cell vertical align m
  • 为什么 mktime 为我的 std::tm 返回 -1

    我有一个std tm看起来是正确的 然而 当标准化时mktime我看到一个 1 根据man mktime The mktime function returns the specified calendar time if the cale
  • PHP 源代码控制服务器

    我有一个基于 PHP 的源代码控制 服务器 与 SVN 客户端兼容 我想将 SVN 托管在我的托管服务器上 但是当前主机不允许我启动任何进程或安装任何软件 你可以尝试 http sourceforge net projects deltaw
  • 文件修订可疑行为?

    今天似乎出现了 GoogleDrive 非本机文件修订版的新问题 几个月来 我们已经通过 Google Drive API 从 C 应用程序成功更新了 Google Drive 帐户中的现有文档 有些文件有 40 60 甚至超过 100 个
  • 如何通过用户id显示数据库中的记录

    我想按用户 ID 显示数据库中的记录 这意味着员工必须输入员工ID和密码并提出新项目的请求 并且该请求将被保存在数据库中 该请求工作正常 但在 request php 页面之后 我想在receipt php 中显示该员工订购的商品 我怎么能
  • IBM Watson - 对话 API 集成返回“未找到资源”错误 (404)

    我正在尝试集成来自 salesforce 的 Watson Http Callout 并收到 404 错误 然后我尝试使用 Postman 工具进行相同的操作 但得到相同的结果 在请求标头中添加了对话凭据 请求端点 https gatewa
  • Python:Selenium xpath 查找具有不区分大小写字符的元素?

    我有能力做到这一点 search View List driver find elements by xpath text normalize space s parent search 但我需要它忽略并将所有元素与文本匹配 例如 VieW
  • iOS Core Plot CPTAxisLabel 与 CTPlot 对齐

    请看下面这张图片 我已附上文件 我的问题是CPTAxisLabel标签 它们被放置在勾号下方 但不被放置在CPTPlot如我所愿 如何向该标签添加左偏移量 我需要将我的标签放置在中间CPTPlot object 更新 void config
  • 如何编写中间带有参数的 PowerShell 别名?

    我正在尝试设置 Windows PowerShell 别名来使用某些参数运行 MinGW 的 g 可执行文件 但是 这些参数需要位于文件名和其他参数之后 我不想经历尝试设置函数之类的麻烦 有没有一种方法可以简单地说 alias mybuil
  • 如何使两种不兼容的类型,但具有相同的成员,可以互换?

    昨天 我们团队中的两个人来找我 提出了一个不常见的问题 我们正在我们的 winforms 应用程序之一中使用第三方组件 所有代码都已经针对它编写了 然后 他们希望将同一供应商提供的另一个第三方组件合并到我们的应用程序中 令他们高兴的是 他们