1

コード ブロック 4 (以下) は、修正に関して途方に暮れているというエラーを表示しています...

私が使用している XML スキーマは次のとおりです。

<?xml version="1.0" encoding="UTF-8" standalone="no" ?>

<!DOCTYPE ctqcfg SYSTEM "cache.dtd">

<cache version="1.0">
    <configuration name="Test">
        <cacheControl>
            <cache name="Customer" mode="off"/>
            <cache name="Vendor" mode="off"/>
            <cache name="Agency" mode="off"/>
            <cache name="Partner" mode="off"/>
        </cacheControl>
    </configuration>

    <configuration name="Production">
        <cacheControl>
            <cache name="Customer" mode="preload"/>
            <cache name="Vendor" mode="dynamic"/>
            <cache name="Agency" mode="dynamic"/>
            <cache name="Partner" mode="dynamic"/>
        </cacheControl>
    </configuration>
</cache>

XML ファイルが読み込まれます

Private XElement As XElement = Nothing

Public Sub Load()
    XElement = XElement.Load(ConfigurationResource)
End Sub

ユーザーが編集する構成を選択すると、選択した構成要素のルートへの参照が保持されます

Private ConfigurationRoot As System.Collections.Generic.IEnumerable(Of System.Xml.Linq.XElement)

Private ConfigurationName_ As String

Public Property ConfigurationName() As String
    Get
        Return ConfigurationName_
    End Get
    Set(ByVal Value As String)
        ConfigurationName_ = Value
        ConfigurationRoot = From Configuration In XElement.<configuration> Where Configuration.@name = Value
    End Set
End Property

キャッシュ名 (この場合は Customer) に対応するキャッシュ モードを取得しようとしています。

Public Property CustomerCache() As String
    Get
        Try
            Return From Cache In ConfigurationRoot.<cacheControl>.<cache> Where Cache.@name = "Customer" Select Cache.@mode
        Catch Exception As Exception
            Return Nothing
        End Try
    End Get
    Set(ByVal Value As String)
        'ToDo
    End Set
End Property

次のエラーが表示されます

System.InvalidCastException was caught
Message=Unable to cast object of type 'WhereSelectEnumerableIterator`2[System.Xml.Linq.XElement,System.String]' to type 'System.String'.

これは、LINQ を使用する最初の日であり、属性へのアクセス方法に関して基本的な誤解があるようです。クエリがコレクションを返しているようで、見つかる可能性のある値は 1 つしかないことを知っています...

4

2 に答える 2

1

.First()またはが必要です.Single()

Return (From Cache In ConfigurationRoot.<cacheControl>.<cache> Where Cache.@name = "Customer" Select Cache.@mode).First()
于 2012-10-03T21:30:49.447 に答える
0

最初の 3 つのコード ブロックはすべて同じ結果を達成しますが、属性のコンテンツにアクセスする方法が少し異なります。

1. 「暗号化された」属性の最初の (そして唯一の) インスタンスの直接の戻り:

Return "true" = (From DBConnections In Configurations.<dbConnection> Where "Customization" = DBConnections.@name Select DBConnections.<password>.@encrypted).Single

2. XElements のコレクションをクエリし、最初の XElement アプローチから「暗号化された」属性を取得します。

Dim Element As IEnumerable(Of XElement) = (From DBConnections In Configurations.<dbConnection> Where "Customization" = DBConnections.@name Select DBConnections.<password>).Single
Return "true" = Element(0).@encrypted

前の例は、.Single 参照が 1 つだけ検出されることを明示的に示しているため、誤解を招く可能性がありますが、実際にはコレクションである (1 つのアイテムのみを含む) 結果を処理する必要があります。属性値を取得するためにコレクションを明示的に処理する必要がないアプローチ 1 と比較すると、さらに混乱します。

3a. コレクションから最初の XElement をクエリし、「暗号化された」属性アプローチをプルします。

Dim Element As XElement = ((From DBConnections In Configurations.<dbConnection> Where "Customization" = DBConnections.@name Select DBConnections.<password>).Single)(0)
Return "true" = Element.@encrypted

この最後の例では、コレクション内の最初のアイテムを参照し、適切なタイプに格納することによって、コレクション内のアイテムを取得するために (1 つのアイテムの) コレクションを処理する必要があるという誤解を招く部分に対処しようとしています。これにより、コレクションについて心配するのをやめて、代わりに本当に関心のあるオブジェクト (この場合は XElement オブジェクト) を扱うことができます。

3b. 最初の XElement オブジェクト内の「暗号化」属性を変更する

Dim Element As XElement = ((From DBConnections In Configurations.<dbConnection> Where "Customization" = DBConnections.@name Select DBConnections.<password>).Single)(0)
If Value Then
    Element.@encrypted = "true"
Else
    Element.@encrypted = "false"
End If

3 つのクエリ アプローチを実行することで、LINQ によって返されるものに関する私のメンタル モデルを明確にすることができました。さらに、「暗号化された」属性を変更するために、ここで実際に何が起こっているのかを理解する必要がありました...

于 2012-10-10T20:37:58.423 に答える