访问 class 库中的 mustoverride 属性 时出现 AccessViolationException

AccessViolationException when accessing a mustoverride property in a class library

这有点复杂,但我会尽量解释清楚。

我有一个 class 通用代码组件库;我尝试制作一些常见的 ConfigurationHandler 基础 classes,以简化创建自定义配置部分、collections 和元素。

我得到的结果是:

ConfigurationSectionBaseclass是泛型,以TConfElementCollection As {ConfigurationElementCollection, New}作为类型约束。

ConfigurationSectionBase class 包含一个 Public MustOverride Property Collection As TConfElementCollection

想法是在使用 class 库的项目中,他们只需覆盖 collection 并使用 <ConfigurationProperty("CollectionName")> 属性对其进行修饰,例如:

<ConfigurationProperty("CollectionName")>
Public Overrides Property Collection As DerivedConfigurationElementCollection
    Get
        Return TryCast(Me("CollectionName"), DerivedConfigurationElementCollection)
    End Get
    Set(value As DerivedConfigurationElementCollection)
        Me("CollectionName") = value
    End Set
End Property

这工作正常 - 在使用应用程序中我可以创建该部分,然后在我的配置处理程序中 class 我可以调用

Dim section As DerivedSection = (TryCast(Config.GetSection("DerivedSection"), DerivedSection))
Dim coll as DerivedConfigurationElementCollection = section?.Collection

然后,我的下一个想法是,为什么不也抽象配置处理程序 class,并将其移动到基 class 中?

事实证明这更复杂,但我最终在 DLL 的 ConfigurationHandlerBase class 中得到以下代码:

Protected Function GetCollection(Of TCollection As ConfigurationElementCollection, TSection As {ConfigurationSectionBase(Of TCollection), New})(sectionName as String) As TCollection
    Dim s As TSection = (TryCast(Config.GetSection(sectionName), TSection))
    Return s?.Collection ' AccessViolationException is thrown on this line

为了尝试诊断问题,我以与 Collection 相同的方式制作了一个字符串 属性(MustOverrideConfigurationSectionBase class在 DLL 中,在使用的应用程序中被覆盖),然后尝试从 class 库访问它 - 同样的问题。

所以我认为这个问题与 MustOverride 和 DLL 代码没有识别出 Derived class 已经覆盖 属性.

有关

如果我 return 来自 DLL 方法的 TSection,则在使用 DLL 的应用程序中访问 Collection 属性;我可以正常访问 Collection。

奇怪的是,如果我放入一个断点,Visual Studio 会很高兴地向我显示 Collection 属性 的内容,而不会抛出任何异常。

此外,如果我将 (TryCast(Config.GetSection(sectionName), TSection)) 替换为 new TSection(),我仍然会收到 AccessViolationException - 所以这与我正在访问配置文件这一事实无关,尽我所能见。

有没有人遇到过这个问题;或者我接下来的步骤是什么来解决这个异常?

您是 vb.net 编译器代码生成错误的受害者,它破坏了 ConfigurationHandlerBase.GetCollection() 方法的代码。它使用约束调用不恰当地优化了集合 属性 的 属性 getter 调用。查看它的最简单方法是在 TestCollection.dll 程序集上 运行 PEVerify.exe,尽管错误消息看起来误导了我:

[IL]: Error: [C:\temp\temp\TestClassLibrary\TestClassLibrary\bin\Debug\testclasslibrary.dll : TestClassLibrary.ConfigurationHandlerBase`1[TDerivedConfigHandler]::GetCollection[TCollection,TSection]][offset 0x00000024] The 'this' argument to a constrained call must have ByRef type. 1 Error(s) Verifying testclasslibrary.dll

搜索错误消息后,您会找到 this github.com issue. Marked as fixed 3 months ago, I think it was 已修复的错误消息。此类修复何时出现在我们的机器上并不总是很明显。不是今天。

github 问题中提出的解决方法似乎无效。我看到的最简单的解决方法是避免 elvis 运算符并回归基础,重写:

   Dim coll As TCollection = s?.Collection
   Return coll

收件人:

   If s Is Nothing Then return Nothing Else Return s.Collection