187 lines
6.8 KiB
C#
187 lines
6.8 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
|
|
namespace Cryville.Common {
|
|
/// <summary>
|
|
/// Provides a set of <see langword="static" /> methods for refletion.
|
|
/// </summary>
|
|
public static class ReflectionHelper {
|
|
static readonly Type[] emptyTypeArray = {};
|
|
/// <summary>
|
|
/// Gets the parameterless constructor of a type.
|
|
/// </summary>
|
|
/// <param name="type">The type.</param>
|
|
/// <returns>The parameterless constructor of the type.</returns>
|
|
public static ConstructorInfo GetEmptyConstructor(Type type) {
|
|
return type.GetConstructor(emptyTypeArray);
|
|
}
|
|
static readonly object[] emptyObjectArray = {};
|
|
/// <summary>
|
|
/// Invokes the parameterless constructor of a type and returns the result.
|
|
/// </summary>
|
|
/// <param name="type">The type.</param>
|
|
/// <returns>The created instance.</returns>
|
|
public static object InvokeEmptyConstructor(Type type) {
|
|
return GetEmptyConstructor(type).Invoke(emptyObjectArray);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tries to find a member with the specified attribute type in a type.
|
|
/// </summary>
|
|
/// <typeparam name="T">The attribute type.</typeparam>
|
|
/// <param name="t">The type containing the member with the specified attribute type.</param>
|
|
/// <param name="mi">The member.</param>
|
|
/// <returns>Whether the member is found.</returns>
|
|
public static bool TryFindMemberWithAttribute<T>(Type t, out MemberInfo mi) where T : Attribute {
|
|
try {
|
|
mi = FindMemberWithAttribute<T>(t);
|
|
return true;
|
|
}
|
|
catch (MissingMemberException) {
|
|
mi = null;
|
|
return false;
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Finds a member with the specified attribute type in a type.
|
|
/// </summary>
|
|
/// <typeparam name="T">The attribute type.</typeparam>
|
|
/// <param name="type">The type containing the member with the specified attribute type.</param>
|
|
/// <returns></returns>
|
|
/// <exception cref="MissingMemberException">The member is not found or multiple members are found.</exception>
|
|
public static MemberInfo FindMemberWithAttribute<T>(Type type) where T : Attribute {
|
|
var mil = type.FindMembers(
|
|
MemberTypes.Field | MemberTypes.Property,
|
|
BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static,
|
|
(m, o) => m.GetCustomAttributes(typeof(T), true).Length != 0,
|
|
null
|
|
);
|
|
if (mil.Length != 1)
|
|
throw new MissingMemberException(type.Name, typeof(T).Name);
|
|
return mil[0];
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets whether a type is a <see cref="Dictionary{TKey, TValue}" />.
|
|
/// </summary>
|
|
/// <param name="type">The type.</param>
|
|
/// <returns>Whether the type is a <see cref="Dictionary{TKey, TValue}" />.</returns>
|
|
public static bool IsGenericDictionary(Type type) {
|
|
return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Dictionary<,>);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the member from a type with the specified name.
|
|
/// </summary>
|
|
/// <param name="type">The type.</param>
|
|
/// <param name="name">The name of the member.</param>
|
|
/// <returns>The member.</returns>
|
|
/// <exception cref="MissingMemberException">The member is not found or multiple members are found.</exception>
|
|
public static MemberInfo GetMember(Type type, string name) {
|
|
var mil = type.GetMember(
|
|
name,
|
|
MemberTypes.Field | MemberTypes.Property,
|
|
BindingFlags.Public | BindingFlags.Instance
|
|
);
|
|
if (mil.Length != 1)
|
|
throw new MissingMemberException(type.Name, name);
|
|
return mil[0];
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the type of a member.
|
|
/// </summary>
|
|
/// <param name="mi">The member.</param>
|
|
/// <returns>The type of the member.</returns>
|
|
/// <exception cref="ArgumentException"><paramref name="mi" /> is not a field or a property.</exception>
|
|
public static Type GetMemberType(MemberInfo mi) {
|
|
if (mi is FieldInfo)
|
|
return ((FieldInfo)mi).FieldType;
|
|
if (mi is PropertyInfo)
|
|
return ((PropertyInfo)mi).PropertyType;
|
|
else
|
|
throw new ArgumentException("Member is not field or property.");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the value of a member of an object.
|
|
/// </summary>
|
|
/// <param name="mi">The member.</param>
|
|
/// <param name="obj">The object.</param>
|
|
/// <returns>The value.</returns>
|
|
/// <exception cref="ArgumentException"><paramref name="mi" /> is not a field or a property.</exception>
|
|
public static object GetValue(MemberInfo mi, object obj) {
|
|
if (mi is FieldInfo)
|
|
return ((FieldInfo)mi).GetValue(obj);
|
|
else if (mi is PropertyInfo)
|
|
return ((PropertyInfo)mi).GetValue(obj, new object[]{});
|
|
else
|
|
throw new ArgumentException();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets the value of a member of an object.
|
|
/// </summary>
|
|
/// <param name="mi">The member.</param>
|
|
/// <param name="obj">The object.</param>
|
|
/// <param name="value">The value.</param>
|
|
/// <param name="binder">An optional binder to convert the value.</param>
|
|
/// <exception cref="ArgumentException"><paramref name="mi" /> is not a field or a property.</exception>
|
|
public static void SetValue(MemberInfo mi, object obj, object value, Binder binder = null) {
|
|
if (mi is FieldInfo)
|
|
((FieldInfo)mi).SetValue(obj, value, BindingFlags.Default, binder, null);
|
|
else if (mi is PropertyInfo)
|
|
((PropertyInfo)mi).SetValue(obj, value, BindingFlags.Default, binder, emptyObjectArray, null);
|
|
else
|
|
throw new ArgumentException();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets all the subclasses of a type in the current app domain.
|
|
/// </summary>
|
|
/// <typeparam name="T">The type.</typeparam>
|
|
/// <returns>An array containing all the subclasses of the type in the current app domain.</returns>
|
|
public static Type[] GetSubclassesOf<T>() where T : class {
|
|
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
|
IEnumerable<Type> r = new List<Type>();
|
|
foreach (var a in assemblies)
|
|
r = r.Concat(a.GetTypes().Where(
|
|
t => t.IsClass
|
|
&& !t.IsAbstract
|
|
&& t.IsSubclassOf(typeof(T))
|
|
));
|
|
return r.ToArray();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets a simple name of a type.
|
|
/// </summary>
|
|
/// <param name="type">The type.</param>
|
|
/// <returns>A simple name of the class.</returns>
|
|
public static string GetSimpleName(Type type) {
|
|
string result = type.Name;
|
|
var typeargs = type.GetGenericArguments();
|
|
if (typeargs.Length > 0) {
|
|
result = string.Format("{0}[{1}]", result, string.Join(",", from a in typeargs select GetSimpleName(a)));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the namespace qualified name of a type.
|
|
/// </summary>
|
|
/// <param name="type">The type.</param>
|
|
/// <returns>The namespace qualified name of the class.</returns>
|
|
public static string GetNamespaceQualifiedName(Type type) {
|
|
string result = type.Namespace + "." + type.Name;
|
|
var typeargs = type.GetGenericArguments();
|
|
if (typeargs.Length > 0) {
|
|
result = string.Format("{0}[{1}]", result, string.Join(",", from a in typeargs select GetNamespaceQualifiedName(a)));
|
|
}
|
|
return result;
|
|
}
|
|
}
|
|
}
|