You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
74 lines
3.4 KiB
74 lines
3.4 KiB
// Author: Gockner, Simon
|
|
// Created: 2020-02-12
|
|
// Copyright(c) 2020 SimonG. All Rights Reserved.
|
|
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using System.Xml.Linq;
|
|
using GBase.DataHandling.Exceptions;
|
|
using GBase.Helpers;
|
|
using GBase.Interfaces.DataHandling;
|
|
using GBase.Interfaces.DataHandling.Xml;
|
|
|
|
namespace GBase.DataHandling
|
|
{
|
|
/// <summary>
|
|
/// A <see cref="IDataReader"/> that reads from a xml file
|
|
/// </summary>
|
|
public class XmlDataReader : IXmlDataReader
|
|
{
|
|
/// <summary>
|
|
/// Read the data of a property
|
|
/// </summary>
|
|
/// <typeparam name="T">The <see cref="Type"/></typeparam>
|
|
/// <typeparam name="TProperty">The <see cref="Type"/> of the property</typeparam>
|
|
/// <param name="file"></param>
|
|
/// <param name="propertyName">The name of the property</param>
|
|
/// <param name="cancellationToken"></param>
|
|
/// <returns>The data of the given property, null if no data found</returns>
|
|
/// <exception cref="ArgumentNullException"><paramref name="propertyName"/></exception>
|
|
/// <exception cref="InvalidOperationException">Invalid <see cref="Type"/> found for the read object</exception>
|
|
public async Task<IEnumerable<TProperty>> Read<T, TProperty>(FileStream file, string propertyName, CancellationToken cancellationToken)
|
|
//TODO: Read currently doesn't work for newly added items -> probably because file was loaded before new items were added; is probably not a problem -> cache
|
|
{
|
|
string typeName = typeof(T).FullName;
|
|
if (typeName == null)
|
|
throw new ArgumentNullException(nameof(typeName));
|
|
|
|
XDocument xmlDocument = await XDocument.LoadAsync(file, LoadOptions.None, cancellationToken);
|
|
file.Seek(0, SeekOrigin.Begin); //reset stream to it's beginning to be able to save it
|
|
|
|
return await Task.Run(() =>
|
|
{
|
|
XElement rootElement = xmlDocument.Root;
|
|
if (rootElement == null)
|
|
throw new InvalidXmlFileException("No root element is set.");
|
|
|
|
XElement propertyElement = rootElement.Element(propertyName);
|
|
XAttribute propertyTypeAttribute = propertyElement?.Attribute(XmlDataHandler.VALUE_TYPE_ATTRIBUTE_NAME);
|
|
if (propertyTypeAttribute == null)
|
|
return null;
|
|
|
|
Type propertyType = Type.GetType(propertyTypeAttribute.Value);
|
|
if (propertyType != typeof(TProperty))
|
|
throw new InvalidOperationException("Invalid Type found for the read object.");
|
|
|
|
List<XElement> valueElements = propertyElement.Elements(XmlDataHandler.VALUE_ELEMENT_NAME).ToList();
|
|
if (!valueElements.Any())
|
|
return null;
|
|
|
|
IEnumerable<string> values = valueElements.Select(v => v.Value);
|
|
|
|
if (typeof(TProperty) != typeof(string) && typeof(TProperty).GetInterfaces().Contains(typeof(IEnumerable))) //read property is an IEnumerable
|
|
return values.Select(Enumerables.ConvertToGBaseEnumerable<TProperty>).ToList();
|
|
|
|
return values.Select(value => (TProperty)Convert.ChangeType(value, typeof(TProperty))).ToList();
|
|
}, cancellationToken);
|
|
}
|
|
}
|
|
} |