using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.InteropServices; namespace ScreenConnect; public static class ReflectionExtensions { public static IEnumerable GetPropertiesX(this Type type) { return type.GetProperties(); } public static bool IsGenericTypeX(this Type type) { return type.IsGenericType; } public static bool IsEnumX(this Type type) { return type.IsEnum; } public static bool IsAbstractX(this Type type) { return type.IsAbstract; } public static bool IsValueTypeX(this Type type) { return type.IsValueType; } public static bool IsPublicX(this Type type) { return type.IsPublic; } public static bool IsAssignableFromX(this Type type, Type otherType) { return type.IsAssignableFrom(otherType); } public static IEnumerable GetInterfacesX(this Type type) { return type.GetInterfaces(); } public static Assembly GetAssemblyX(this Type type) { return type.Assembly; } public static Type[] GetGenericArgumentsX(this Type type) { return type.GetGenericArguments(); } public static IEnumerable GetCustomAttributes(this Type type) where T : Attribute { return type.GetCustomAttributes(inherit: true).OfType(); } public static T? GetCustomAttribute(this Type type) where T : Attribute { return type.GetCustomAttributes(typeof(T), inherit: true).OfType().FirstOrDefault(); } public static IEnumerable GetTypesX(this Assembly assembly) { try { return assembly.GetTypes(); } catch (ReflectionTypeLoadException ex) { TypeTrace.TraceException(ex); return Array.FindAll(ex.Types, (Type t) => (object)t != null); } } public static T GetCustomAttribute(this MemberInfo memberInfo) where T : Attribute { return (T)Attribute.GetCustomAttribute(memberInfo, typeof(T), inherit: true); } public static T GetCustomAttribute(this Assembly assembly) where T : Attribute { return (T)assembly.GetCustomAttributes(typeof(T), inherit: true).FirstOrDefault(); } public static MethodInfo GetGetMethodX(this PropertyInfo propertyInfo) { return propertyInfo.GetGetMethod(); } public static MethodInfo GetSetMethodX(this PropertyInfo propertyInfo) { return propertyInfo.GetSetMethod(); } public static int SizeOfType() { return Marshal.SizeOf(typeof(T)); } public static T PtrToStructure(IntPtr ptr) { return (T)Marshal.PtrToStructure(ptr, typeof(T)); } public static AssemblyBuilder DefineDynamicAssembly(AssemblyName assemblyName, AssemblyBuilderAccess assemblyBuilderAccess) { return AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, assemblyBuilderAccess); } public static bool IsDynamicX(this Assembly assembly) { return assembly.ManifestModule.GetType().Namespace.StartsWith("System.Reflection.Emit"); } public static FieldInfo DemandInstanceFieldX(this Type type, string fieldName) { return (from _ in type.GetAncestors((Type _) => _.BaseType, includeSelf: true) select _.GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetField)).WhereNotNull().First(); } public static object GetFieldValue(this object obj, string fieldName) { return obj.GetType().DemandInstanceFieldX(fieldName).GetValue(obj); } public static object GetFieldValue(this Type type, string fieldName) { return type.InvokeMemberHandlingTargetInvocationException(fieldName, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetField, null, null, null); } public static void SetFieldValue(this object obj, string fieldName, object value) { obj.GetType().DemandInstanceFieldX(fieldName).SetValue(obj, value); } public static void SetFieldValue(this Type type, string fieldName, object value) { type.InvokeMemberHandlingTargetInvocationException(fieldName, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.SetField, null, null, new object[1] { value }); } public static bool HasProperty(this object obj, string propertyName) { return (object)obj.GetType().GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) != null; } public static object GetPropertyValue(this object obj, string propertyName) { return obj.GetType().InvokeMemberHandlingTargetInvocationException(propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetProperty, null, obj, null); } public static object GetPropertyValue(this Type type, string propertyName) { return type.InvokeMemberHandlingTargetInvocationException(propertyName, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetProperty, null, null, null); } public static object GetPropertyValue(this object obj, string propertyName, params object[] indexerValues) { return obj.GetType().InvokeMemberHandlingTargetInvocationException(propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetProperty, null, obj, indexerValues); } public static void SetPropertyValue(this object obj, string propertyName, object value) { obj.GetType().InvokeMemberHandlingTargetInvocationException(propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.SetProperty, null, obj, new object[1] { value }); } public static void SetPropertyValue(this Type type, string propertyName, object value) { type.InvokeMemberHandlingTargetInvocationException(propertyName, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.SetProperty, null, null, new object[1] { value }); } public static void SetPropertyValue(this object obj, string propertyName, object value, params object[] indexerValues) { obj.GetType().InvokeMemberHandlingTargetInvocationException(propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.SetProperty, null, obj, indexerValues.Concat(value.ToSingleElementArray()).ToArray()); } public static object InvokeMethod(this object obj, string methodName, params object[] args) { return obj.GetType().InvokeMemberHandlingTargetInvocationException(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, obj, args); } public static object InvokeMethod(this object obj, Type baseType, string methodName, params object[] args) { return baseType.InvokeMemberHandlingTargetInvocationException(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, obj, args); } public static object InvokeGenericMethod(this object obj, string methodName, Type[] genericTypeArguments, params object[] args) { MethodInfo method = obj.GetType().GetGenericMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, genericTypeArguments, args.SelectToArray((object it) => it?.GetType())); return Extensions.PerformUnwrappingInnerException(() => method.Invoke(obj, args)); } public static object TryInvokeMethod(this object obj, string methodName, params object[] args) { return Extensions.TryGet(() => obj.GetType().InvokeMember(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, obj, args)); } public static object InvokeMethod(this Type type, string methodName, params object[] args) { return type.InvokeMemberHandlingTargetInvocationException(methodName, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, args); } public static object InvokeGenericMethod(this Type type, string methodName, Type[] genericTypeArguments, params object[] args) { MethodInfo method = type.GetGenericMethod(methodName, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, genericTypeArguments, args.SelectToArray((object it) => it?.GetType())); return Extensions.PerformUnwrappingInnerException(() => method.Invoke(null, args)); } public static object TryInvokeMethod(this Type type, string methodName, params object[] args) { return Extensions.TryGet(() => type.InvokeMember(methodName, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, null, args)); } public static object InvokeMemberHandlingTargetInvocationException(this Type type, string name, BindingFlags invokeAttr, Binder binder, object target, object[] args) { return Extensions.PerformUnwrappingInnerException(() => type.InvokeMember(name, invokeAttr, binder, target, args)); } public static object InvokeHandlingTargetInvocationException(this MethodInfo methodInfo, object target, params object[] parameters) { return Extensions.PerformUnwrappingInnerException(() => methodInfo.Invoke(target, parameters)); } public static bool IsObsolete(this Enum value) { return value.GetType().GetField(value.ToString()).IsDefined(typeof(ObsoleteAttribute), inherit: false); } public static MethodInfo GetGenericMethod(this Type type, string name, BindingFlags bindingFlags, Type[] genericTypeArguments, Type?[] parameterTypes) { return (from it in (from it in type.GetMethods(bindingFlags) where it.Name == name where it.IsGenericMethodDefinition where it.GetGenericArguments().Length == genericTypeArguments.Length select it).TrySelect((MethodInfo it) => it.MakeGenericMethod(genericTypeArguments)).WhereNotNull() where it.GetParameters().Zip(parameterTypes).All<(ParameterInfo, Type)>(((ParameterInfo, Type) tuple) => tuple.Item2?.IsOfType(tuple.Item1.ParameterType) ?? true) select it).First(); } public static object CreateValueTuple(Type type1, object value1, Type type2, object value2) { return typeof(ValueTuple<, >).MakeGenericType(type1, type2).GetConstructor(new Type[2] { type1, type2 }).AssertNonNull() .Invoke(new object[2] { value1, value2 }); } public static object CreateValueTuple(Type type1, object value1, Type type2, object value2, Type type3, object value3) { return typeof(ValueTuple<, , >).MakeGenericType(type1, type2, type3).GetConstructor(new Type[3] { type1, type2, type3 }).AssertNonNull() .Invoke(new object[3] { value1, value2, value3 }); } }