// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.Loader;
using FlaxEngine.Interop;
namespace FlaxEngine
{
///
/// Class with helper functions.
///
public static partial class Utils
{
///
/// Copies data from one memory location to another using an unmanaged memory pointers.
///
/// Uses low-level platform impl.
/// The source location.
/// The destination location.
/// The length (amount of bytes to copy).
[Obsolete("Use MemoryCopy with long length and source/destination swapped to match C++ API.")]
public static void MemoryCopy(IntPtr source, IntPtr destination, int length)
{
// [Deprecated on 30.05.2021, expires on 30.05.2022]
MemoryCopy(destination, source, (ulong)length);
}
///
/// Copies data from one memory location to another using an unmanaged memory pointers.
///
/// Uses low-level platform impl.
/// The source location.
/// The destination location.
/// The length (amount of bytes to copy).
[LibraryImport("FlaxEngine", EntryPoint = "PlatformInternal_MemoryCopy")]
public static partial void MemoryCopy(IntPtr destination, IntPtr source, ulong length);
///
/// Clears the memory region with zeros.
///
/// Uses low-level platform impl.
/// Destination memory address
/// Size of the memory to clear in bytes
[LibraryImport("FlaxEngine", EntryPoint = "PlatformInternal_MemoryClear")]
public static partial void MemoryClear(IntPtr dst, ulong size);
///
/// Compares two blocks of the memory.
///
/// Uses low-level platform impl.
/// The first buffer address.
/// The second buffer address.
/// Size of the memory to compare in bytes.
[LibraryImport("FlaxEngine", EntryPoint = "PlatformInternal_MemoryCompare")]
public static partial int MemoryCompare(IntPtr buf1, IntPtr buf2, ulong size);
///
/// Rounds the floating point value up to 1 decimal place.
///
/// The value.
/// The rounded result.
public static float RoundTo1DecimalPlace(float value)
{
return (float)Math.Round(value * 10) / 10;
}
///
/// Rounds the floating point value up to 2 decimal places.
///
/// The value.
/// The rounded result.
public static float RoundTo2DecimalPlaces(float value)
{
return (float)Math.Round(value * 100) / 100;
}
///
/// Rounds the floating point value up to 3 decimal places.
///
/// The value.
/// The rounded result.
public static float RoundTo3DecimalPlaces(float value)
{
return (float)Math.Round(value * 1000) / 1000;
}
///
/// Gets the empty array of the given type (shared one).
///
/// The type.
/// The empty array object.
public static T[] GetEmptyArray()
{
#if USE_NETCORE
return Array.Empty();
#else
return Enumerable.Empty() as T[];
#endif
}
///
/// Determines whether two arrays are equal by comparing the elements by using the default equality comparer for their type.
///
/// The type of the elements of the input sequences.
/// The first array.
/// The second array.
/// true if the two source sequences are of equal length and their corresponding elements are equal according to the default equality comparer for their type; otherwise, false.
public static bool ArraysEqual(T[] a1, T[] a2)
{
if (ReferenceEquals(a1, a2))
return true;
if (a1 == null || a2 == null)
return false;
if (a1.Length != a2.Length)
return false;
var comparer = EqualityComparer.Default;
for (int i = 0; i < a1.Length; i++)
{
if (!comparer.Equals(a1[i], a2[i]))
return false;
}
return true;
}
///
/// Determines whether two arrays are equal by comparing the elements by using the default equality comparer for their type.
///
/// The type of the elements of the input sequences.
/// The first array.
/// The second array.
/// true if the two source sequences are of equal length and their corresponding elements are equal according to the default equality comparer for their type; otherwise, false.
public static bool ArraysEqual(T[] a1, IReadOnlyList a2)
{
if (a1 == null || a2 == null)
return false;
if (a1.Length != a2.Count)
return false;
var comparer = EqualityComparer.Default;
for (int i = 0; i < a1.Length; i++)
{
if (!comparer.Equals(a1[i], a2[i]))
return false;
}
return true;
}
///
/// Determines whether two arrays are equal by comparing the elements by using the default equality comparer for their type.
///
/// The type of the elements of the input sequences.
/// The first array.
/// The second array.
/// true if the two source sequences are of equal length and their corresponding elements are equal according to the default equality comparer for their type; otherwise, false.
public static bool ArraysEqual(List a1, List a2)
{
if (ReferenceEquals(a1, a2))
return true;
if (a1 == null || a2 == null)
return false;
if (a1.Count != a2.Count)
return false;
var comparer = EqualityComparer.Default;
for (int i = 0; i < a1.Count; i++)
{
if (!comparer.Equals(a1[i], a2[i]))
return false;
}
return true;
}
///
/// Gets all currently loaded assemblies in the runtime.
///
/// List of assemblies
public static Assembly[] GetAssemblies()
{
#if USE_NETCORE
return AssemblyLoadContext.Default.Assemblies.Concat(NativeInterop.scriptingAssemblyLoadContext.Assemblies).ToArray();
#else
return AppDomain.CurrentDomain.GetAssemblies();
#endif
}
///
/// Gets the assembly with the given name.
///
/// The name.
/// The assembly or null if not found.
public static Assembly GetAssemblyByName(string name)
{
return GetAssemblyByName(name, GetAssemblies());
}
///
/// Gets the assembly with the given name.
///
/// The name.
/// The assemblies collection to search for.
/// The assembly or null if not found.
public static Assembly GetAssemblyByName(string name, Assembly[] assemblies)
{
Assembly result = null;
for (int i = 0; i < assemblies.Length; i++)
{
var assemblyName = assemblies[i].GetName();
if (assemblyName.Name == name)
{
result = assemblies[i];
break;
}
}
return result;
}
///
/// Gets the location of the assembly.
///
/// The assembly.
/// Path in the filesystem
public static string GetAssemblyLocation(Assembly assembly)
{
#if USE_NETCORE
var location = assembly.Location;
if (!string.IsNullOrEmpty(location))
return location;
if (Interop.NativeInterop.AssemblyLocations.TryGetValue(assembly.FullName, out location))
return location;
return null;
#else
return assembly.Location;
#endif
}
#if USE_MONO
internal static T[] ExtractArrayFromList(List list)
{
return list != null ? (T[])Internal_ExtractArrayFromList(list) : null;
}
#else
private class ExtractArrayFromListContext
{
public static FieldInfo itemsField;
}
internal static T[] ExtractArrayFromList(List list)
{
if (list == null)
return null;
if (ExtractArrayFromListContext.itemsField == null)
{
Type listType = typeof(List);
ExtractArrayFromListContext.itemsField = listType.GetField("_items", BindingFlags.NonPublic | BindingFlags.Instance);
}
return (T[])ExtractArrayFromListContext.itemsField.GetValue(list); // boxing is slower;
}
#endif
internal static Float2[] ConvertCollection(Vector2[] v)
{
// [Deprecated on 26.05.2022, expires on 26.05.2024]
Float2[] result = null;
if (v != null && v.Length != 0)
{
result = new Float2[v.Length];
for (int i = 0; i < v.Length; i++)
result[i] = v[i];
}
return result;
}
internal static List ConvertCollection(List v)
{
// [Deprecated on 26.05.2022, expires on 26.05.2024]
List result = null;
if (v != null && v.Count != 0)
{
result = new List();
result.Capacity = v.Count;
for (int i = 0; i < v.Count; i++)
result.Add(v[i]);
}
return result;
}
internal static Float3[] ConvertCollection(Vector3[] v)
{
// [Deprecated on 26.05.2022, expires on 26.05.2024]
Float3[] result = null;
if (v != null && v.Length != 0)
{
result = new Float3[v.Length];
for (int i = 0; i < v.Length; i++)
result[i] = v[i];
}
return result;
}
internal static List ConvertCollection(List v)
{
// [Deprecated on 26.05.2022, expires on 26.05.2024]
List result = null;
if (v != null && v.Count != 0)
{
result = new List();
result.Capacity = v.Count;
for (int i = 0; i < v.Count; i++)
result.Add(v[i]);
}
return result;
}
internal static Float4[] ConvertCollection(Vector4[] v)
{
// [Deprecated on 26.05.2022, expires on 26.05.2024]
Float4[] result = null;
if (v != null && v.Length != 0)
{
result = new Float4[v.Length];
for (int i = 0; i < v.Length; i++)
result[i] = v[i];
}
return result;
}
internal static List ConvertCollection(List v)
{
// [Deprecated on 26.05.2022, expires on 26.05.2024]
List result = null;
if (v != null && v.Count != 0)
{
result = new List();
result.Capacity = v.Count;
for (int i = 0; i < v.Count; i++)
result.Add(v[i]);
}
return result;
}
#if USE_NETCORE
#else
[LibraryImport("FlaxEngine", EntryPoint = "UtilsInternal_ExtractArrayFromList")]
[return: MarshalUsing(typeof(FlaxEngine.SystemArrayMarshaller))]
internal static partial Array Internal_ExtractArrayFromList([MarshalUsing(typeof(FlaxEngine.GCHandleMarshaller))] object list);
#endif
///
/// Reads the color from the binary stream.
///
/// The stream.
/// The value.
public static Color32 ReadColor32(this BinaryReader stream)
{
return new Color32(stream.ReadByte(), stream.ReadByte(), stream.ReadByte(), stream.ReadByte());
}
///
/// Reads the color from the binary stream.
///
/// The stream.
/// The value.
public static Color ReadColor(this BinaryReader stream)
{
return new Color(stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle());
}
///
/// Reads the Vector2 from the binary stream.
///
/// The stream.
/// The value.
public static Vector2 ReadVector2(this BinaryReader stream)
{
return new Vector2(stream.ReadSingle(), stream.ReadSingle());
}
///
/// Reads the Vector3 from the binary stream.
///
/// The stream.
/// The value.
public static Vector3 ReadVector3(this BinaryReader stream)
{
return new Vector3(stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle());
}
///
/// Reads the Vector4 from the binary stream.
///
/// The stream.
/// The value.
public static Vector4 ReadVector4(this BinaryReader stream)
{
return new Vector4(stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle());
}
///
/// Reads the Vector2 from the binary stream.
///
/// The stream.
/// True to explicitly use 64-bit precision for serialized data, otherwise will use 32-bit precision.
/// The value.
public static Vector2 ReadVector2(this BinaryReader stream, bool useDouble)
{
if (useDouble)
return new Vector2(stream.ReadDouble(), stream.ReadDouble());
return new Vector2(stream.ReadSingle(), stream.ReadSingle());
}
///
/// Reads the Vector3 from the binary stream.
///
/// The stream.
/// True to explicitly use 64-bit precision for serialized data, otherwise will use 32-bit precision.
/// The value.
public static Vector3 ReadVector3(this BinaryReader stream, bool useDouble)
{
if (useDouble)
return new Vector3(stream.ReadDouble(), stream.ReadDouble(), stream.ReadDouble());
return new Vector3(stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle());
}
///
/// Reads the Vector4 from the binary stream.
///
/// The stream.
/// True to explicitly use 64-bit precision for serialized data, otherwise will use 32-bit precision.
/// The value.
public static Vector4 ReadVector4(this BinaryReader stream, bool useDouble)
{
if (useDouble)
return new Vector4(stream.ReadDouble(), stream.ReadDouble(), stream.ReadDouble(), stream.ReadDouble());
return new Vector4(stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle());
}
///
/// Reads the Float2 from the binary stream.
///
/// The stream.
/// The value.
public static Float2 ReadFloat2(this BinaryReader stream)
{
return new Float2(stream.ReadSingle(), stream.ReadSingle());
}
///
/// Reads the Float3 from the binary stream.
///
/// The stream.
/// The value.
public static Float3 ReadFloat3(this BinaryReader stream)
{
return new Float3(stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle());
}
///
/// Reads the Float4 from the binary stream.
///
/// The stream.
/// The value.
public static Float4 ReadFloat4(this BinaryReader stream)
{
return new Float4(stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle());
}
///
/// Reads the Double2 from the binary stream.
///
/// The stream.
/// The value.
public static Double2 ReadDouble2(this BinaryReader stream)
{
return new Double2(stream.ReadDouble(), stream.ReadDouble());
}
///
/// Reads the Double3 from the binary stream.
///
/// The stream.
/// The value.
public static Double3 ReadDouble3(this BinaryReader stream)
{
return new Double3(stream.ReadDouble(), stream.ReadDouble(), stream.ReadDouble());
}
///
/// Reads the Double4 from the binary stream.
///
/// The stream.
/// The value.
public static Double4 ReadDouble4(this BinaryReader stream)
{
return new Double4(stream.ReadDouble(), stream.ReadDouble(), stream.ReadDouble(), stream.ReadDouble());
}
///
/// Reads the Int2 from the binary stream.
///
/// The stream.
/// The value.
public static Int2 ReadInt2(this BinaryReader stream)
{
return new Int2(stream.ReadInt32(), stream.ReadInt32());
}
///
/// Reads the Int3 from the binary stream.
///
/// The stream.
/// The value.
public static Int3 ReadInt3(this BinaryReader stream)
{
return new Int3(stream.ReadInt32(), stream.ReadInt32(), stream.ReadInt32());
}
///
/// Reads the Int4 from the binary stream.
///
/// The stream.
/// The value.
public static Int4 ReadInt4(this BinaryReader stream)
{
return new Int4(stream.ReadInt32(), stream.ReadInt32(), stream.ReadInt32(), stream.ReadInt32());
}
///
/// Reads the Quaternion from the binary stream.
///
/// The stream.
/// The value.
public static Quaternion ReadQuaternion(this BinaryReader stream)
{
return new Quaternion(stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle());
}
///
/// Reads the BoundingBox from the binary stream.
///
/// The stream.
/// The value.
public static BoundingBox ReadBoundingBox(this BinaryReader stream)
{
return new BoundingBox(stream.ReadVector3(), stream.ReadVector3());
}
///
/// Reads the BoundingSphere from the binary stream.
///
/// The stream.
/// The value.
public static BoundingSphere ReadBoundingSphere(this BinaryReader stream)
{
return new BoundingSphere(stream.ReadVector3(), stream.ReadSingle());
}
///
/// Reads the Ray from the binary stream.
///
/// The stream.
/// The value.
public static Ray ReadRay(this BinaryReader stream)
{
return new Ray(stream.ReadVector3(), stream.ReadVector3());
}
///
/// Reads the Transform from the binary stream.
///
/// The stream.
/// The value.
public static Transform ReadTransform(this BinaryReader stream)
{
return new Transform(stream.ReadVector3(), stream.ReadQuaternion(), stream.ReadVector3());
}
///
/// Reads the Matrix from the binary stream.
///
/// The stream.
/// The value.
public static Matrix ReadMatrix(this BinaryReader stream)
{
return new Matrix(stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle(), stream.ReadSingle());
}
internal static byte[] ReadJsonBytes(this BinaryReader stream)
{
// ReadStream::ReadJson
var engineBuild = stream.ReadInt32();
var size = stream.ReadInt32();
return stream.ReadBytes(size);
}
///
/// Deserializes object from Json by reading it as a raw data (ver+length+bytes).
///
/// Reads version number, data length and actual data bytes from the stream.
/// The stream.
/// The object to deserialize.
public static void ReadJson(this BinaryReader stream, ISerializable obj)
{
// ReadStream::ReadJson
var engineBuild = stream.ReadInt32();
var size = stream.ReadInt32();
if (obj != null)
{
var data = stream.ReadBytes(size);
Json.JsonSerializer.LoadFromBytes(obj, data, engineBuild);
}
else
stream.BaseStream.Seek(size, SeekOrigin.Current);
}
///
/// Writes the color to the binary stream.
///
/// The stream.
/// The value to write.
public static void Write(this BinaryWriter stream, Color32 value)
{
stream.Write(value.R);
stream.Write(value.G);
stream.Write(value.B);
stream.Write(value.A);
}
///
/// Writes the color to the binary stream.
///
/// The stream.
/// The value to write.
public static void Write(this BinaryWriter stream, Color value)
{
stream.Write(value.R);
stream.Write(value.G);
stream.Write(value.B);
stream.Write(value.A);
}
///
/// Writes the Vector2 to the binary stream.
///
/// The stream.
/// The value to write.
public static void Write(this BinaryWriter stream, Vector2 value)
{
stream.Write((float)value.X);
stream.Write((float)value.Y);
}
///
/// Writes the Vector3 to the binary stream.
///
/// The stream.
/// The value to write.
public static void Write(this BinaryWriter stream, Vector3 value)
{
stream.Write((float)value.X);
stream.Write((float)value.Y);
stream.Write((float)value.Z);
}
///
/// Writes the Vector4 to the binary stream.
///
/// The stream.
/// The value to write.
public static void Write(this BinaryWriter stream, Vector4 value)
{
stream.Write((float)value.X);
stream.Write((float)value.Y);
stream.Write((float)value.Z);
stream.Write((float)value.W);
}
///
/// Writes the Vector2 to the binary stream.
///
/// The stream.
/// The value to write.
/// True to explicitly use 64-bit precision for serialized data, otherwise will use 32-bit precision.
public static void Write(this BinaryWriter stream, Vector2 value, bool useDouble)
{
if (useDouble)
{
stream.Write((double)value.X);
stream.Write((double)value.Y);
}
else
{
stream.Write((float)value.X);
stream.Write((float)value.Y);
}
}
///
/// Writes the Vector3 to the binary stream.
///
/// The stream.
/// The value to write.
/// True to explicitly use 64-bit precision for serialized data, otherwise will use 32-bit precision.
public static void Write(this BinaryWriter stream, Vector3 value, bool useDouble)
{
if (useDouble)
{
stream.Write((double)value.X);
stream.Write((double)value.Y);
stream.Write((double)value.Z);
}
else
{
stream.Write((float)value.X);
stream.Write((float)value.Y);
stream.Write((float)value.Z);
}
}
///
/// Writes the Vector4 to the binary stream.
///
/// The stream.
/// The value to write.
/// True to explicitly use 64-bit precision for serialized data, otherwise will use 32-bit precision.
public static void Write(this BinaryWriter stream, Vector4 value, bool useDouble)
{
if (useDouble)
{
stream.Write((double)value.X);
stream.Write((double)value.Y);
stream.Write((double)value.Z);
stream.Write((double)value.W);
}
else
{
stream.Write((float)value.X);
stream.Write((float)value.Y);
stream.Write((float)value.Z);
stream.Write((float)value.W);
}
}
///
/// Writes the Vector2 to the binary stream.
///
/// The stream.
/// The value to write.
public static void Write(this BinaryWriter stream, Float2 value)
{
stream.Write(value.X);
stream.Write(value.Y);
}
///
/// Writes the Vector3 to the binary stream.
///
/// The stream.
/// The value to write.
public static void Write(this BinaryWriter stream, Float3 value)
{
stream.Write(value.X);
stream.Write(value.Y);
stream.Write(value.Z);
}
///
/// Writes the Vector4 to the binary stream.
///
/// The stream.
/// The value to write.
public static void Write(this BinaryWriter stream, Float4 value)
{
stream.Write(value.X);
stream.Write(value.Y);
stream.Write(value.Z);
stream.Write(value.W);
}
///
/// Writes the Vector2 to the binary stream.
///
/// The stream.
/// The value to write.
public static void Write(this BinaryWriter stream, Double2 value)
{
stream.Write(value.X);
stream.Write(value.Y);
}
///
/// Writes the Vector3 to the binary stream.
///
/// The stream.
/// The value to write.
public static void Write(this BinaryWriter stream, Double3 value)
{
stream.Write(value.X);
stream.Write(value.Y);
stream.Write(value.Z);
}
///
/// Writes the Vector4 to the binary stream.
///
/// The stream.
/// The value to write.
public static void Write(this BinaryWriter stream, Double4 value)
{
stream.Write(value.X);
stream.Write(value.Y);
stream.Write(value.Z);
stream.Write(value.W);
}
///
/// Writes the Int2 to the binary stream.
///
/// The stream.
/// The value to write.
public static void Write(this BinaryWriter stream, Int2 value)
{
stream.Write(value.X);
stream.Write(value.Y);
}
///
/// Writes the Int3 to the binary stream.
///
/// The stream.
/// The value to write.
public static void Write(this BinaryWriter stream, Int3 value)
{
stream.Write(value.X);
stream.Write(value.Y);
stream.Write(value.Z);
}
///
/// Writes the Int4 to the binary stream.
///
/// The stream.
/// The value to write.
public static void Write(this BinaryWriter stream, Int4 value)
{
stream.Write(value.X);
stream.Write(value.Y);
stream.Write(value.Z);
stream.Write(value.W);
}
///
/// Writes the Quaternion to the binary stream.
///
/// The stream.
/// The value to write.
public static void Write(this BinaryWriter stream, Quaternion value)
{
stream.Write(value.X);
stream.Write(value.Y);
stream.Write(value.Z);
stream.Write(value.W);
}
///
/// Writes the BoundingBox to the binary stream.
///
/// The stream.
/// The value to write.
public static void Write(this BinaryWriter stream, BoundingBox value)
{
stream.Write(value.Minimum);
stream.Write(value.Maximum);
}
///
/// Writes the BoundingSphere to the binary stream.
///
/// The stream.
/// The value to write.
public static void Write(this BinaryWriter stream, BoundingSphere value)
{
stream.Write(value.Center);
stream.Write(value.Radius);
}
///
/// Writes the Transform to the binary stream.
///
/// The stream.
/// The value to write.
public static void Write(this BinaryWriter stream, Transform value)
{
stream.Write(value.Translation);
stream.Write(value.Orientation);
stream.Write(value.Scale);
}
///
/// Writes the Rectangle to the binary stream.
///
/// The stream.
/// The value to write.
public static void Write(this BinaryWriter stream, Rectangle value)
{
stream.Write(value.Location);
stream.Write(value.Size);
}
///
/// Writes the Ray to the binary stream.
///
/// The stream.
/// The value to write.
public static void Write(this BinaryWriter stream, Ray value)
{
stream.Write(value.Position);
stream.Write(value.Direction);
}
///
/// Writes the Matrix to the binary stream.
///
/// The stream.
/// The value to write.
public static void Write(this BinaryWriter stream, Matrix value)
{
stream.Write(value.M11);
stream.Write(value.M12);
stream.Write(value.M13);
stream.Write(value.M14);
stream.Write(value.M21);
stream.Write(value.M22);
stream.Write(value.M23);
stream.Write(value.M24);
stream.Write(value.M31);
stream.Write(value.M32);
stream.Write(value.M33);
stream.Write(value.M34);
stream.Write(value.M41);
stream.Write(value.M42);
stream.Write(value.M43);
stream.Write(value.M44);
}
internal static void WriteJsonBytes(this BinaryWriter stream, byte[] bytes)
{
// WriteStream::WriteJson
stream.Write(Globals.EngineBuildNumber);
if (bytes != null)
{
stream.Write(bytes.Length);
stream.Write(bytes);
}
else
stream.Write(0);
}
///
/// Serializes object to Json and writes it as a raw data (ver+length+bytes).
///
/// The stream.
/// Writes version number, data length and actual data bytes to the stream.
/// The object to serialize.
public static void WriteJson(this BinaryWriter stream, ISerializable obj)
{
// WriteStream::WriteJson
stream.Write(Globals.EngineBuildNumber);
if (obj != null)
{
var bytes = Json.JsonSerializer.SaveToBytes(obj);
stream.Write(bytes.Length);
stream.Write(bytes);
}
else
stream.Write(0);
}
///
/// Initializes the structure (value type) by inflating it with values from (recursive).
///
/// The object to initialize.
/// The structure type.
public static void InitStructure(object obj, Type type)
{
var fields = type.GetFields(BindingFlags.Default | BindingFlags.Instance | BindingFlags.Public);
for (var i = 0; i < fields.Length; i++)
{
var field = fields[i];
var fieldType = field.FieldType;
var attr = field.GetCustomAttribute();
if (attr != null)
{
var value = attr.Value;
if (value != null && value.GetType() != fieldType)
value = Convert.ChangeType(value, fieldType);
field.SetValue(obj, value);
}
else if (fieldType.IsValueType)
{
var fieldValue = Activator.CreateInstance(fieldType);
InitStructure(fieldValue, fieldType);
field.SetValue(obj, fieldValue);
}
}
}
///
/// Gets the array of method parameter types.
///
/// The method to get it's parameters.
/// Method parameters array.
public static Type[] GetParameterTypes(this MethodBase method)
{
Type[] parameterTypes;
var parameters = method.GetParameters();
if (parameters.Length != 0)
{
parameterTypes = new Type[parameters.Length];
for (int i = 0; i < parameters.Length; i++)
parameterTypes[i] = parameters[i].ParameterType;
}
else
parameterTypes = Array.Empty();
return parameterTypes;
}
}
}