【问题标题】:AccessViolationException when accessing a mustoverride property in a class library访问类库中的 mustoverride 属性时出现 AccessViolationException
【发布时间】:2018-02-16 10:14:48
【问题描述】:

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

我有一个通用代码组件的类库;我尝试创建一些通用的ConfigurationHandler 基类,以简化创建自定义配置部分、集合和元素的过程。

我最终得到的是:

ConfigurationSectionBase 类是泛型的,将TConfElementCollection As {ConfigurationElementCollection, New} 作为类型约束。

这个ConfigurationSectionBase 类包含一个Public MustOverride Property Collection As TConfElementCollection

这个想法是,在使用类库的项目中,他们只需覆盖集合并用<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

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

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

然后,我的下一个想法是,为什么不将 Config Handler 类也抽象出来,并将其移至基类中?

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

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 相同的方式创建了一个 String 属性(DLL 中的 ConfigurationSectionBase 类中的MustOverride,在使用应用程序中被覆盖),然后尝试从类中访问它图书馆 - 又是同样的问题。

所以我认为问题与MustOverride 和 DLL 代码没有识别派生类已覆盖属性有关。

如果我从 DLL 方法返回 TSection,则在使用 DLL 的应用程序中访问 Collection 属性;我可以正常访问收藏集。

奇怪的是,如果我在其中设置断点,Visual Studio 会很高兴地向我显示 Collection 属性的内容,而不会抛出任何异常。

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

以前有没有人遇到过这种情况?或者我接下来的步骤是什么来解决这个异常?

【问题讨论】:

  • 看起来像是带有泛型的空条件运算符上的编译器或抖动错误(尚未仔细查看哪个)。将Dim coll As TCollection = s?.Collection 替换为Dim coll As TCollection = IIf(s Is Nothing, Nothing, s.Collection),问题就消失了。当然,如果编译器工作正常,这些语句应该是等价的。

标签: vb.net inheritance dll access-violation


【解决方案1】:

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

[IL]:错误:[C:\temp\temp\TestClassLibrary\TestClassLibrary\bin\Debug\testclasslibrary.dll:TestClassLibrary.ConfigurationHandlerBase`1[TDerivedConfigHandler]::GetCollection[TCollection,TSection]][偏移量 0x00000024] 'this' 论点 受约束的调用必须具有 ByRef 类型。 1 验证 testclasslibrary.dll 的错误

搜索错误消息后,您将访问this github.com issue。 3 个月前标记为已修复,我认为是 this SO question 修复了它。当这样的修复出现在我们的机器上时,并不总是很明显。今天不行。

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

   Dim coll As TCollection = s?.Collection
   Return coll

收件人:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-16
    相关资源
    最近更新 更多