我遇到了以前从未见过的问题。
我正在使用有两个不同版本的第 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 应该可以工作
我了解到,在编译时,即使您通过派生类的公共接口调用访问它,您也会获得对定义成员的(基)类的引用。
是的,发生这种情况是因为当您针对 V2.0.0 进行编译时,编译器将“P2”专门绑定到类“B”。在 V1.0.0 中,“P2”位于 A 中,因此在运行时,.NET 找不到“B.P2”,并且会出现错误。
尽管看起来 P2 在哪里并不重要,但编译器期望它准确地位于您构建代码时的位置。由于 P2 属于不同的类,.NET 将其视为缺失。
一种解决方法是使用反射,它可以让您在运行时检查“P2”,而不必关心它是在“A”还是“B”中。然而,反射可能会更慢并且有点混乱。如果您可以控制加载的版本,另一个选择可以是设置程序集重定向,但这也可能会变得复杂。
不幸的是,由于版本之间的更改是“破坏性的”,因此如果没有不同版本的应用程序或像反射这样的代码调整,就无法直接修复。