访问 class 库中的 mustoverride 属性 时出现 AccessViolationException
AccessViolationException when accessing a mustoverride property in a class library
这有点复杂,但我会尽量解释清楚。
我有一个 class 通用代码组件库;我尝试制作一些常见的 ConfigurationHandler
基础 classes,以简化创建自定义配置部分、collections 和元素。
我得到的结果是:
ConfigurationSectionBase
class是泛型,以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 相同的方式制作了一个字符串 属性(MustOverride
在 ConfigurationSectionBase
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
这有点复杂,但我会尽量解释清楚。
我有一个 class 通用代码组件库;我尝试制作一些常见的 ConfigurationHandler
基础 classes,以简化创建自定义配置部分、collections 和元素。
我得到的结果是:
ConfigurationSectionBase
class是泛型,以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 相同的方式制作了一个字符串 属性(MustOverride
在 ConfigurationSectionBase
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