Ошибка компилятора для файла .resx со ссылкой на Enum и TypeConverter его собственной сборки - PullRequest
0 голосов
/ 14 января 2020

Первый подход: Сборка A относится к сборке B. Для этого созвездия я узнал, как создать файл .resx для сборки A, который содержит перечисление, определенное в сборке B. Таким же образом, Я сделал так, чтобы файл .resx содержал объект, для которого существует TypeConverter в сборке B.

Однако реальная цель состоит в том, чтобы я сделал без сборки B. И Enum, и TypeConverter должны быть в сборке A. Однако при попытке Visual Studio сообщает об ошибке компиляции. Я подозреваю, что проблема круговая: resgen.exe может получить доступ к моему Enum и моему TypeConverter только после создания сборки A, сборка A может быть создана только после того, как файл .resx был скомпилирован.

Есть ли у кого-нибудь какие-либо идея?

Редактировать

1. Мое перечисление ESecurityContextAttributes

a. ESecurityContextAttributes реализация:

<Flags>
Public Enum ESecurityContextAttributes As Int32
    None = 0
    ' other values
End Enum

b. ESecurityContextAttributes значение в файле .resx:

<assembly alias="NDToolsCommon0" name="NDToolsCommon0, Version=5.2.0.1, Culture=neutral, PublicKeyToken=null" />
<data name="TlsStreamInContextAttributes" type="NDTools.Common.WindowsAndInteroperability.ESecurityContextAttributes, NDToolsCommon0">
    <value>ReplayDetect, SequenceDetect, Confidentiality, InitStream, AcceptStream</value>
</data>

c. Ошибка для значения ESecurityContextAttributes:

Ошибка MSB3103. Ungültige ResX-Datei. Der Typ NDTools.Common.WindowsAndInteroperability.ESecurityContextAttributes, NDToolsCommon0, версия = 5.2.0.1, культура = нейтральная, PublicKeyToken = ноль в ленте Daten в Zeile 401, позиция 4, kann nicht gefunden werden. [engli sh: Недопустимый файл Resx. Тип ... не найден.]

2. Мой объект ConfigStringList

a. ConfigStringList реализация:

<Serializable>
<TypeConverter(GetType(ConfigListTypeConverter(Of String, ConfigStringList)))>
Public NotInheritable Class ConfigStringList
Inherits ConfigBaseList(Of String, ConfigStringList)
    Public Sub New()
        MyBase.New
    End Sub
    Public Sub New(ByVal valValues As IEnumerable(Of String))
        MyBase.New(valValues)
    End Sub
    Private Sub New(serializationInfo As SerializationInfo, streamingContext As StreamingContext)
        MyBase.New(serializationInfo, streamingContext)
    End Sub
End Class

b. ConfigBaseList реализация:

<Serializable>
Public MustInherit Class ConfigBaseList(Of TItem As {IConvertible, IEquatable(Of TItem)}, TList As {New, Class, IList(Of TItem)})
Inherits List(Of TItem)
Implements ISerializable
    Protected Sub New()
        MyBase.New()
    End Sub
    Protected Sub New(ByVal valValues As IEnumerable(Of TItem))
        MyBase.New(valValues)
    End Sub
    Protected Sub New(ByVal valInfo As SerializationInfo, ByVal valContext As StreamingContext)
        AddRange(DirectCast((New ConfigListTypeConverter(Of TItem, TList)).ConvertFrom(DirectCast(valInfo.GetValue("Values", GetType(String)), String)), ConfigBaseList(Of TItem, TList)))
    End Sub
    Friend Sub GetObjectData(info As SerializationInfo, context As StreamingContext) Implements ISerializable.GetObjectData
        info.AddValue("Values", (New ConfigListTypeConverter(Of TItem, TList)).ConvertTo(Me, GetType(String)))
    End Sub
End Class

c. ConfigListTypeConverter реализация:

Public NotInheritable Class ConfigListTypeConverter(Of TItem As {IConvertible, IEquatable(Of TItem)}, TList As {New, Class, IList(Of TItem)})
Inherits TypeConverter
    Private ReadOnly _converter As New ConvertibleConverter
    Public Sub New()
        MyBase.New
    End Sub
    Public Overrides Function CanConvertTo(context As ITypeDescriptorContext, destinationType As Type) As Boolean
        If destinationType.GetType = GetType(Design.Serialization.InstanceDescriptor) Then
            Return True
        Else
            Return MyBase.CanConvertTo(context, destinationType)
        End If
    End Function
    Public Overrides Function CanConvertFrom(ByVal context As ITypeDescriptorContext, ByVal sourceType As Type) As Boolean
        Return sourceType = GetType(String)
    End Function
    Public Overrides Function ConvertFrom(ByVal context As ITypeDescriptorContext, ByVal culture As CultureInfo, ByVal value As Object) As Object
        Dim valuesString As String
        valuesString = TryCast(value, String)
        If valuesString IsNot Nothing Then
            Return _ParseValueString(valuesString)
        Else
            Return MyBase.ConvertFrom(context, culture, value)
        End If
    End Function
    Public Overrides Function ConvertTo(ByVal context As ITypeDescriptorContext, ByVal culture As CultureInfo, ByVal value As Object, ByVal destinationType As Type) As Object
        Dim values As TList
        Dim ctor As ConstructorInfo
        values = TryCast(value, TList)
        If values IsNot Nothing AndAlso destinationType = GetType(String) Then
            Return String.Join(",", values.Select(Function(dlgValue As TItem) _converter.Write(dlgValue, CultureInfo.InvariantCulture).Replace("\", "\\").Replace(",", "\,")))
        ElseIf destinationType = GetType(Design.Serialization.InstanceDescriptor) AndAlso values IsNot Nothing Then
            ctor = GetType(TList).GetConstructor({GetType(IEnumerable(Of TItem))})
            Return New Design.Serialization.InstanceDescriptor(ctor, {values})
        Else
            Return MyBase.ConvertTo(context, culture, value, destinationType)
        End If
    End Function

    Public Overrides Function GetProperties(context As ITypeDescriptorContext, value As Object, attributes() As Attribute) As PropertyDescriptorCollection
        Return Nothing
    End Function
    Public Overrides Function GetPropertiesSupported(context As ITypeDescriptorContext) As Boolean
        Return False
    End Function
    Private Function _ParseValueString(ByVal valValues As String) As TList
        Dim isSingleBackslash As Boolean
        Dim currentPosCtr As Int32
        Dim previousPosCtr As Int32
        Dim length As Int32
        Dim values As TList
        values = New TList
        Do While currentPosCtr < valValues.Length
            If (Not isSingleBackslash AndAlso valValues(currentPosCtr).Equals(","c)) OrElse currentPosCtr = valValues.Length - 1 Then
                If currentPosCtr = valValues.Length - 1 Then
                    length = currentPosCtr - previousPosCtr + 1
                Else
                    length = currentPosCtr - previousPosCtr
                End If
                values.Add(_converter.ReadAs(Of TItem)(valValues.Substring(previousPosCtr, length).Replace("\,", ",").Replace("\\", "\"), CultureInfo.InvariantCulture))
                previousPosCtr = currentPosCtr + 1
            End If
            If valValues(currentPosCtr).Equals("\"c) Then
                isSingleBackslash = Not isSingleBackslash
            ElseIf isSingleBackslash Then
                isSingleBackslash = False
            End If
            currentPosCtr += 1
        Loop
        Return values
    End Function
End Class

d. ConfigStringList в файле .resx:

<assembly alias="NDToolsCommon0" name="NDToolsCommon0, Version=5.2.0.1, Culture=neutral, PublicKeyToken=null" />
<data name="FtpResponseDateTimeFormats" type="NDTools.Common.Programming.ConfigStringList, NDToolsCommon0">
    <value>yyyyMMddHHmm,yyyyMMddHHmmss</value>
</data>

e. Ошибка для ConfigStringList значение:

ошибка MSB3103: Ungültige ResX-Datei. Der Typ NDTools.Common.Programming.ConfigStringList, NDToolsCommon0, версия = 5.2.0.1, культура = нейтральная, PublicKeyToken = ноль в дате Daten в Zeile 401, позиция 4, kann nicht gefunden werden. [engli sh: Недействительный файл Resx. Тип ... не может быть найден.]

Я проверил все пространства имен. Они установлены правильно. То же самое для версии сборки.

...