访问类库中的mustoverride属性时发生AccessViolationException

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

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

我有一个用于公共代码组件的类库;我尝试制作一些常见的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中的MustOverride类中的ConfigurationSectionBase,在使用的应用程序中被覆盖),然后尝试从类库中访问它 - 再次,同样问题。

所以我认为这个问题与MustOverride和DLL代码无关,因为它没有认识到Derived类已经覆盖了Property。

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

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

另外,如果我用(TryCast(Config.GetSection(sectionName), TSection))替换new TSection(),我仍然会得到一个AccessViolationException - 所以这与我访问配置文件的事实无关,据我所见。

有没有人遇到过这个问题;或者我的下一步可以解决此异常的问题?

vb.net inheritance dll access-violation
1个回答
9
投票

您是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]] [offset 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
© www.soinside.com 2019 - 2024. All rights reserved.