using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace Cryville.Common {
///
/// Provides a set of methods for refletion.
///
public static class ReflectionHelper {
static readonly Type[] emptyTypeArray = {};
///
/// Gets the parameterless constructor of a type.
///
/// The type.
/// The parameterless constructor of the type.
public static ConstructorInfo GetEmptyConstructor(Type type) {
return type.GetConstructor(emptyTypeArray);
}
static readonly object[] emptyObjectArray = {};
///
/// Invokes the parameterless constructor of a type and returns the result.
///
/// The type.
/// The created instance.
public static object InvokeEmptyConstructor(Type type) {
return GetEmptyConstructor(type).Invoke(emptyObjectArray);
}
///
/// Tries to find a member with the specified attribute type in a type.
///
/// The attribute type.
/// The type containing the member with the specified attribute type.
/// The member.
/// Whether the member is found.
public static bool TryFindMemberWithAttribute(Type t, out MemberInfo mi) where T : Attribute {
try {
mi = FindMemberWithAttribute(t);
return true;
}
catch (MissingMemberException) {
mi = null;
return false;
}
}
///
/// Finds a member with the specified attribute type in a type.
///
/// The attribute type.
/// The type containing the member with the specified attribute type.
///
/// The member is not found or multiple members are found.
public static MemberInfo FindMemberWithAttribute(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];
}
///
/// Gets whether a type is a .
///
/// The type.
/// Whether the type is a .
public static bool IsGenericDictionary(Type type) {
return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Dictionary<,>);
}
///
/// Gets the member from a type with the specified name.
///
/// The type.
/// The name of the member.
/// The member.
/// The member is not found or multiple members are found.
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];
}
///
/// Gets the type of a member.
///
/// The member.
/// The type of the member.
/// is not a field or a property.
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.");
}
///
/// Gets the value of a member of an object.
///
/// The member.
/// The object.
/// The value.
/// is not a field or a property.
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();
}
///
/// Sets the value of a member of an object.
///
/// The member.
/// The object.
/// The value.
/// An optional binder to convert the value.
/// is not a field or a property.
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();
}
///
/// Gets all the subclasses of a type in the current app domain.
///
/// The type.
/// An array containing all the subclasses of the type in the current app domain.
public static Type[] GetSubclassesOf() where T : class {
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
IEnumerable r = Enumerable.Empty();
foreach (var a in assemblies)
r = r.Concat(a.GetTypes().Where(
t => t.IsClass
&& !t.IsAbstract
&& t.IsSubclassOf(typeof(T))
));
return r.ToArray();
}
///
/// Gets a simple name of a type.
///
/// The type.
/// A simple name of the class.
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;
}
///
/// Gets the namespace qualified name of a type.
///
/// The type.
/// The namespace qualified name of the class.
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;
}
}
}