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


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

我有一个用于公共代码组件的类库;我试着做一些共同点 ConfigurationHandler 基类,以简化创建自定义配置节,集合和元素。

我最终得到的是:

ConfigurationSectionBase 上课是通用的,服用 TConfElementCollection As {ConfigurationElementCollection, New} 作为类型约束。

这个 ConfigurationSectionBase class包含一个 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类,并将其移到基类中?

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

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属性(MustOverride 在里面 ConfigurationSectionBase 在DLL中的类,在使用的应用程序中重写),然后尝试从类库中访问它 - 再次,同样的问题。

所以我认为问题与此有关 MustOverride 并且DLL代码无法识别Derived类是否已重写Property。

如果我回来了 TSection 从DLL方法改为,然后访问 Collection 使用DLL的应用程序中的属性;我可以访问收藏品。

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

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

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


3531
2018-02-16 10:14


起源

@HansPassant看 dropbox.com/s/ios84hb46jul649/Projects.zip?dl=0 - simonalexander2005
看起来像带有泛型的null条件运算符上的编译器或抖动错误(尚未密切关注哪一个)。更换 Dim coll As TCollection = s?.Collection 同 Dim coll As TCollection = IIf(s Is Nothing, Nothing, s.Collection) 问题就消失了。当然,如果编译器工作正常,这些语句应该是等效的。 - Jeroen Mostert


答案:


您是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

然而,搜索错误消息会让您入侵 这个github.com问题。 3个月前标记为固定,我认为是 这个问题 得到它修复。当这些修复程序进入我们的机器时,并不总是很明显。今天不行。

github问题中提出的解决方法似乎没有效果。我看到的最简单的解决方法是避免使用elvis操作符并返回基础,重写:

   Dim coll As TCollection = s?.Collection
   Return coll

至:

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

9
2018-02-21 11:26



太漂亮了,谢谢! - simonalexander2005