【发布时间】:2015-06-23 14:12:43
【问题描述】:
假设我们在 C# 中定义了一个基本接口,如下所示:
interface IBase
{
int Prop1 { get; set }
string Prop2 { get; set }
}
那么我们有一个派生接口如下:
interface ISub1: IBase
{
int Prop3 { get; set }
}
这些接口是在 API 程序集中定义的,自定义应用程序根据该程序集编译和运行。 (该程序集还包括实现这些接口的非公开类和用于获取实例的公共工厂方法)。所有现存代码都使用ISub1,没有直接引用IBase的现有代码。这样做是因为我们预计我们最终可能想要引入第二个派生接口ISub2,作为ISub1 的对等体,现在已经实现。不幸的是,尽管我们发现 ISub2 不应该包含 Prop2(只有 Prop1 和一些额外的独特属性),因此我们希望将该属性“降级”为 ISub1,从而导致以下修改后的接口:
interface IBase
{
int Prop1 { get; set }
}
interface ISub1: IBase
{
string Prop2 { get; set }
int Prop3 { get; set }
}
interface ISub2: IBase
{
string Prop4 { get; set }
}
鉴于没有 IBase 的消费者,我们似乎应该能够不受惩罚地做到这一点(我相当确定我们可以在 Java 中做到这一点),但在尝试这样做时,我们遇到了针对旧接口定义编译的代码的二进制兼容性问题。具体来说:
ISub1 s1 = ... // get an instance
s1.Prop2 = "help";
此代码在针对新的接口定义运行时会失败,并出现如下异常:
System.MissingMethodException:找不到方法:'无效 MyNamespace.IBase.set_Prop2(System.String)'。
注意对IBase 的引用。我认为这是因为对ISub1.set_Prop2 的看似调用已编译为与Prop2 实际引入的位置紧密绑定,在IBase 中。
谁能帮我解决这个难题? IE。有没有办法重新考虑接口,以便 ISub2 的定义是“干净的”(不包括无关的 Prop2)?要求所有现有应用程序重新编译是不可能的。
【问题讨论】:
-
你被卡住了。
-
我用 C# 编写 OOP 代码超过 8 年,我不明白你的问题。您应该只检查接口是否未更改,并且您的构建具有相同的 .Net/interface 版本。而且.. C#/net 中没有二进制 vtable
-
如果IBase定义了Prop2,而ISub2实现了IBase,那么ISub2也必须实现Prop2。这似乎是一个非常简单的问题。
-
能否总结一下前后的结构?从您的文章中似乎有点不清楚 Prop2 是在哪里定义和定义的。
-
进行了一些编辑以使其(希望)更清楚目标是什么。
标签: c# .net interface backwards-compatibility missingmethodexception