将公共属性移至基类是公共 API 中的重大更改

问题描述 投票:0回答:1

我遇到了以前从未见过的问题。

我正在使用有两个不同版本的第 3 方程序集。我针对其中之一进行编译并在运行时加载正确的版本。

我编译的版本看起来像(V2.0.0)

public class A { public int P2 { get; set; } }
public class B : A { public int P1 { get; set; } }

我在运行时加载的看起来像(V1.0.0)

public class A { public int P1 { get; set; } public int P2 { get; set;} }
public class B : A { }

调用程序集中的代码如下所示

public static void Main() {
    var b = new B();
    b.P2 = 3;
}

令我惊讶的是,

b.P2
在运行时加载 V1.0.0 失败。

直觉上我可以理解它。编译版本引用了不存在的 B::P2,但这似乎很奇怪,因为 B::P2 位于 B 的公共 API 中,并且它恰好在 A::P2 中实现,这是一个不应该的细节t(或者我希望它不应该)重要。

我当然可以通过针对正确版本“重新编译”来解决它,但我认为问题将出在 V2.0.0 上。

有没有办法避免我的应用程序有 2 个版本?

如果重要的话,第 3 方程序集是 .NetFramework,我的代码是 DotNet 8。

编辑:抱歉我弄错了课程。

V1.0.0 看起来像这样

public class B { public int P1 { get; set; } public int P2 { get; set;} }

这意味着从V2.0.0编译的版本来看,该方法转移到了更派生的类(从A到B)。在 @canton7 链接的文档中,这似乎是一个重大更改。

但这也意味着使用 V1.0.0 进行编译并加载 V2.0.0 应该可以工作

  • 添加没有抽象/虚拟成员的基类是允许的。
  • 允许将成员移动到基类。

我了解到,在编译时,即使您通过派生类的公共接口调用访问它,您也会获得对定义成员的(基)类的引用。

c# inheritance assembly-loading
1个回答
0
投票

是的,发生这种情况是因为当您针对 V2.0.0 进行编译时,编译器将“P2”专门绑定到类“B”。在 V1.0.0 中,“P2”位于 A 中,因此在运行时,.NET 找不到“B.P2”,并且会出现错误。

尽管看起来 P2 在哪里并不重要,但编译器期望它准确地位于您构建代码时的位置。由于 P2 属于不同的类,.NET 将其视为缺失。

一种解决方法是使用反射,它可以让您在运行时检查“P2”,而不必关心它是在“A”还是“B”中。然而,反射可能会更慢并且有点混乱。如果您可以控制加载的版本,另一个选择可以是设置程序集重定向,但这也可能会变得复杂。

不幸的是,由于版本之间的更改是“破坏性的”,因此如果没有不同版本的应用程序或像反射这样的代码调整,就无法直接修复。

© www.soinside.com 2019 - 2024. All rights reserved.