【问题标题】:Is there a difference between implementing an interface vs adding a new method?实现接口与添加新方法之间有区别吗?
【发布时间】:2019-05-22 17:06:35
【问题描述】:

如下代码所示,在两个不同的程序集中定义了两个接口IFoo

/// assembly A
interface IFoo {
    void DoSomething()
}

/// assembly B
interface IFoo {
    void DoSomething()

    void DoSomethingElse()
}

/// assembly C
class Bar : IFoo {
    public virtual void DoSomething()

    public virtual void DoSomethingElse()
}

假设程序集 A 和程序集 B 错误地具有相同的签名(程序集弱名称或强名称)。为 Bar 类生成的 MSIL 是否会因构建时使用的是程序集 A 还是程序集而有所不同?

换句话说,假设我们在运行时使用程序集 A 和 C 构建一个项目,在运行时将 A 替换为程序集 B 是否可以?否则我会得到诸如“IFoo.DoSomethingElse”之类的异常没有实现,因为在构建过程中DoSomethingElse被认为是一种新方法,而不是在接口中实现现有方法。

【问题讨论】:

  • AssemblyA.IFoo 是与 AssemblyB.IFoo 不同的类型。它们具有相同的形状并不重要。如果你想动态构造一个对象,那么需要有一个类型,两个/所有目标类型共享(通过继承)。
  • 您是否试图在不重新编译依赖程序以改变行为的情况下有意换出 DLL,您是否试图确保恶意用户在运行时不会更改 DLL,从而改变其行为?试图防止由于巧合的名称冲突或其他原因而意外改变行为?
  • @KennethK.as 我已经提到,这两个程序集具有相同的强名称。
  • @Servy,我正在尝试将 DLL 替换为“hacky”热修复程序。这是一个复杂的故事,但简而言之,我们的一个服务目前正在抛出异常,因为升级了依赖项(向其接口添加了一个方法),但由于某些原因,我们不能简单地在运行时升级依赖项,所以我是想知道我是否可以在编译时简单地“添加一个新方法”,并希望它会在运行时“实现”该接口。
  • C# v8 的默认接口方法特性就是为了解决这类问题。为时已晚,您必须编辑/重建该程序集。

标签: c# .net clr gac-msil


【解决方案1】:

接口映射是在构建时创建的,如果在构建时使用“程序集 A”(1 个方法)而不是 Foo 类将只映射其接口映射中的一个方法。

当创建类的实例时,它将尝试使用运行时可用的接口(与您的情况在编译时使用的接口不必相同),并且将无法映射新的第二种方法。

在 C# 8 之前确实没有很好的方法来解决它 - 您要么必须降级依赖以使其接口向后兼容,要么使用新版本的依赖重新编译您的代码。

如果预计这是常见问题,您可以考虑使用默认方法实现从“程序集 A”公开基类,以允许向接口添加方法并从该类而不是接口派生您的 Foo

正如 Hans Passant 指出的那样,C# 8 引入了default interface methods 来解决这个确切的问题。

【讨论】:

  • 默认接口方法只有在您有远见在第一个程序集中添加该方法的默认实现时才能解决问题,因为知道它的不同实现者可能希望稍后提供一个实现,这甚至假设该接口的所有实例都有一些合理的默认行为。
  • @Servy - 是的......但是没有它,接口的所有者每次需要添加方法时都会坚持添加IFoo3:IFoo2:IFoo 新接口。 (这是好是坏还有待商榷……但我喜欢除了突破性变化与新界面之外还有一个选择)
  • 我并不是说这个功能永远不会有用,我只是说它没有解决想要在界面中添加新功能而不需要重新编译代码的具体问题实现它的类(即使该类已经有合适的方法)。
  • 我们有一个使用插件策略的项目。每个插件都必须实现一个接口,每个插件都是它自己的程序集和自己的构建。随着时间的推移,我们有数百个这样的插件。然后我们想添加一个新方法。使用默认接口方法,我们是否可以不只是将新方法添加到具有默认实现的接口中,而不必重新编译数百个插件?我相信这个功能就是为了解决这个直接的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-10-24
  • 2020-07-27
  • 2020-07-24
  • 2021-01-11
  • 2014-01-22
  • 2011-03-23
  • 2017-09-19
相关资源
最近更新 更多