summaryrefslogtreecommitdiff
path: root/ThirdParty/CsvHelper-master/src/CsvHelper/ReflectionHelper.cs
diff options
context:
space:
mode:
Diffstat (limited to 'ThirdParty/CsvHelper-master/src/CsvHelper/ReflectionHelper.cs')
-rw-r--r--ThirdParty/CsvHelper-master/src/CsvHelper/ReflectionHelper.cs204
1 files changed, 204 insertions, 0 deletions
diff --git a/ThirdParty/CsvHelper-master/src/CsvHelper/ReflectionHelper.cs b/ThirdParty/CsvHelper-master/src/CsvHelper/ReflectionHelper.cs
new file mode 100644
index 0000000..b026186
--- /dev/null
+++ b/ThirdParty/CsvHelper-master/src/CsvHelper/ReflectionHelper.cs
@@ -0,0 +1,204 @@
+// Copyright 2009-2022 Josh Close
+// This file is a part of CsvHelper and is dual licensed under MS-PL and Apache 2.0.
+// See LICENSE.txt for details or visit http://www.opensource.org/licenses/ms-pl.html for MS-PL and http://opensource.org/licenses/Apache-2.0 for Apache 2.0.
+// https://github.com/JoshClose/CsvHelper
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using CsvHelper.Configuration;
+using CsvHelper.Configuration.Attributes;
+
+namespace CsvHelper
+{
+ /// <summary>
+ /// Common reflection tasks.
+ /// </summary>
+ internal static class ReflectionHelper
+ {
+ /// <summary>
+ /// Gets the <see cref="PropertyInfo"/> from the type where the property was declared.
+ /// </summary>
+ /// <param name="type">The type the property belongs to.</param>
+ /// <param name="property">The property to search.</param>
+ /// <param name="flags">Flags for how the property is retrieved.</param>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static PropertyInfo GetDeclaringProperty(Type type, PropertyInfo property, BindingFlags flags)
+ {
+ if (property.DeclaringType != type)
+ {
+ var declaringProperty = property.DeclaringType.GetProperty(property.Name, flags);
+ return GetDeclaringProperty(property.DeclaringType, declaringProperty, flags);
+ }
+
+ return property;
+ }
+
+ /// <summary>
+ /// Gets the <see cref="FieldInfo"/> from the type where the field was declared.
+ /// </summary>
+ /// <param name="type">The type the field belongs to.</param>
+ /// <param name="field">The field to search.</param>
+ /// <param name="flags">Flags for how the field is retrieved.</param>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static FieldInfo GetDeclaringField(Type type, FieldInfo field, BindingFlags flags)
+ {
+ if (field.DeclaringType != type)
+ {
+ var declaringField = field.DeclaringType.GetField(field.Name, flags);
+ return GetDeclaringField(field.DeclaringType, declaringField, flags);
+ }
+
+ return field;
+ }
+
+ /// <summary>
+ /// Walk up the inheritance tree collecting properties. This will get a unique set of properties in the
+ /// case where parents have the same property names as children.
+ /// </summary>
+ /// <param name="type">The <see cref="Type"/> to get properties for.</param>
+ /// <param name="flags">The flags for getting the properties.</param>
+ /// <param name="overwrite">If true, parent class properties that are hidden by `new` child properties will be overwritten.</param>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static List<PropertyInfo> GetUniqueProperties(Type type, BindingFlags flags, bool overwrite = false)
+ {
+ var ignoreBase = type.GetCustomAttribute(typeof(IgnoreBaseAttribute)) != null;
+
+ var properties = new Dictionary<string, PropertyInfo>();
+
+ flags |= BindingFlags.DeclaredOnly;
+ var currentType = type;
+ while (currentType != null)
+ {
+ var currentProperties = currentType.GetProperties(flags);
+ foreach (var property in currentProperties)
+ {
+ if (!properties.ContainsKey(property.Name) || overwrite)
+ {
+ properties[property.Name] = property;
+ }
+ }
+
+ if (ignoreBase)
+ {
+ break;
+ }
+
+ currentType = currentType.BaseType;
+ }
+
+ return properties.Values.ToList();
+ }
+
+ /// <summary>
+ /// Walk up the inheritance tree collecting fields. This will get a unique set of fields in the
+ /// case where parents have the same field names as children.
+ /// </summary>
+ /// <param name="type">The <see cref="Type"/> to get fields for.</param>
+ /// <param name="flags">The flags for getting the fields.</param>
+ /// <param name="overwrite">If true, parent class fields that are hidden by `new` child fields will be overwritten.</param>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static List<FieldInfo> GetUniqueFields(Type type, BindingFlags flags, bool overwrite = false)
+ {
+ var ignoreBase = type.GetCustomAttribute(typeof(IgnoreBaseAttribute)) != null;
+
+ var fields = new Dictionary<string, FieldInfo>();
+
+ flags |= BindingFlags.DeclaredOnly;
+ var currentType = type;
+ while (currentType != null)
+ {
+ var currentFields = currentType.GetFields(flags);
+ foreach (var field in currentFields)
+ {
+ if (!fields.ContainsKey(field.Name) || overwrite)
+ {
+ fields[field.Name] = field;
+ }
+ }
+
+ if (ignoreBase)
+ {
+ break;
+ }
+
+ currentType = currentType.BaseType;
+ }
+
+ return fields.Values.ToList();
+ }
+
+ /// <summary>
+ /// Gets the property from the expression.
+ /// </summary>
+ /// <typeparam name="TModel">The type of the model.</typeparam>
+ /// <typeparam name="TProperty">The type of the property.</typeparam>
+ /// <param name="expression">The expression.</param>
+ /// <returns>The <see cref="PropertyInfo"/> for the expression.</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static MemberInfo GetMember<TModel, TProperty>(Expression<Func<TModel, TProperty>> expression)
+ {
+ var member = GetMemberExpression(expression.Body).Member;
+ var property = member as PropertyInfo;
+ if (property != null)
+ {
+ return property;
+ }
+
+ var field = member as FieldInfo;
+ if (field != null)
+ {
+ return field;
+ }
+
+ throw new ConfigurationException($"'{member.Name}' is not a member.");
+ }
+
+ /// <summary>
+ /// Gets the member inheritance chain as a stack.
+ /// </summary>
+ /// <typeparam name="TModel">The type of the model.</typeparam>
+ /// <typeparam name="TProperty">The type of the property.</typeparam>
+ /// <param name="expression">The member expression.</param>
+ /// <returns>The inheritance chain for the given member expression as a stack.</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Stack<MemberInfo> GetMembers<TModel, TProperty>(Expression<Func<TModel, TProperty>> expression)
+ {
+ var stack = new Stack<MemberInfo>();
+
+ var currentExpression = expression.Body;
+ while (true)
+ {
+ var memberExpression = GetMemberExpression(currentExpression);
+ if (memberExpression == null)
+ {
+ break;
+ }
+
+ stack.Push(memberExpression.Member);
+ currentExpression = memberExpression.Expression;
+ }
+
+ return stack;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static MemberExpression? GetMemberExpression(Expression expression)
+ {
+ MemberExpression? memberExpression = null;
+ if (expression.NodeType == ExpressionType.Convert)
+ {
+ var body = (UnaryExpression)expression;
+ memberExpression = body.Operand as MemberExpression;
+ }
+ else if (expression.NodeType == ExpressionType.MemberAccess)
+ {
+ memberExpression = expression as MemberExpression;
+ }
+
+ return memberExpression;
+ }
+ }
+}