Прежде всего, я хочу поблагодарить Chrissie1 за то, что вдохновили меня получить ответ.Для всех остальных вот мое решение.
Сначала я создал класс для представления каждой строки в результирующем CSV-файле.
Public Class MetaDataValue
Inherits SortedDictionary(Of Integer, String)
''' <summary>
''' creates a comma seperated string of all data
''' </summary>
''' <returns></returns>
''' <remarks></remarks>
Public Overrides Function ToString() As String
' some code to create a comma separated string of all data contained in the sorted dictionary
End Function
End Class
Я использовал отсортированный словарь, потому что он сортирует все данные по ключу, который является целым числом.Таким образом, вы уверены, что все данные отсортированы в индексе.Кроме того, использование словаря обеспечивает способ добавления данных в коллекцию без исключения ошибок из индекса.
После этого вам нужен способ собрать все значения metadataValues.Поэтому я создал класс:
''' <summary>
''' This class respresents a listItemCollection as provided in the constructor as table like data with headers and rows
''' </summary>
''' <remarks></remarks>
Public Class MetadataValuesFactory
Private _fieldsNotToStore As List(Of String) = ConfigurationService.FieldValuesNotToStore
Private _headers As MetaDataValue = New MetaDataValue()
Private _rows As IList(Of MetaDataValue) = New List(Of MetaDataValue)
''' <summary>
''' returns a metaDAtvaleu object that contains all header values
''' </summary>
''' <returns></returns>
''' <remarks></remarks>
Public Function GetHeaders() As MetaDataValue
Dim result As MetaDataValue = New MetaDataValue()
Dim displaynames = ConfigurationService.FieldValueDisplayNames
For Each item In Me._headers
Dim displayname = String.Empty
If (displaynames.ContainsKey(item.Value)) Then
result.Add(item.Key, displaynames.Item(item.Value))
Else
result.Add(item.Key, item.Value)
End If
Next
Return result
End Function
''' <summary>
''' Returns all rows that represent the values
''' </summary>
''' <returns></returns>
''' <remarks></remarks>
Public Function GetRows() As IList(Of MetaDataValue)
Return _rows
End Function
''' <summary>
''' Creates a new metadatavaluesstore with the specified values
''' </summary>
''' <param name="listItems"></param>
''' <remarks></remarks>
Sub New(listItems As ListItemCollection)
'first store all values and make sure keys and values are matched
Dim totalListItems = listItems.Count
For index As Integer = 0 To totalListItems - 1
Dim valuesToStore As MetaDataValue = New MetaDataValue()
Dim item As SPClient.ListItem = listItems(index)
Dim fieldValues = item.FieldValues
For Each fieldValue In fieldValues
If (Not _fieldsNotToStore.Contains(fieldValue.Key)) Then 'If it is not in this collection is must be stored
'Get index of field in _headers
Dim headerindex As Integer = _headers.Values.ToList().IndexOf(fieldValue.Key.ToString)
If (headerindex = -1) Then 'If fieldValue.Key is already in the array it doesn't need to be stored again (-1 = no index found)
'If Not exists then store header/key in _headers ánd set previous index to index of new headers value
headerindex = _headers.Count '' Add new header
_headers.Add(headerindex, fieldValue.Key.ToString)
End If
'add value to valuesstore
Dim valueToStore As String
If (fieldValue.Value Is Nothing) Then
valueToStore = String.Empty
Else
valueToStore = fieldValue.Value.ToString
End If
valuesToStore.Add(headerindex, valueToStore)
End If
Next
_rows.Add(valuesToStore)
Next
End Sub
End Class
NB. Я назвал это фабрикой, я не совсем уверен, что это правильный способ использования этого шаблона.Но это не может быть (обычной) моделью, потому что этот код использует службу конфигурации.Вы также не можете назвать это услугой, поэтому я остановился на фабрике.
Используя эти два класса, вы можете намного проще использовать данные, содержащиеся на фабрике.Например, в моем исходном решении я изменил некоторые значения с отображаемыми именами.Как предположил Крисси1, это можно изменить.Как вы можете видеть, я теперь делаю это методом, который получает все заголовки.Таким образом, это своего рода поздняя связь;внутри используются исходные значения, в то время как снаружи видны только значения, разрешенные фабрикой.Таким образом, эта логика содержится внутри фабрики.Если в какой-то момент в будущем потребуются новые функции, легко получить доступ к заголовкам и значениям по отдельности.
Код, пишущий файл CSV, теперь гораздо более понятен:
metaDataStreamWriter.WriteLine(metadataFactory.GetHeaders.ToString)
For Each storeValue In metadataFactory.GetRows
metaDataStreamWriter.WriteLine(storeValue.ToString)
Next
В любом случае это решило мою проблему.Большое спасибо еще раз за предоставление обратной связи и за урок.Если у вас есть комментарии, пожалуйста, предоставьте.