While working on one of my projects I actively used Reflection. While working with class Type
I expected methods: TryGetMember
, TryGetProperty
, TryGetField
, TryGetMethod
. I've implemented them as extension methods:
public static class TypeExtensions
{
private const BindingFlags DEFAULT_LOOKUP = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public;
/// <summary>
/// Searches for the specified members, using the specified binding constraints.
/// </summary>
/// <param name="name">The string containing the name of the members to get.</param>
/// <param name="bindingAttr">
/// A bitmask comprised of one or more System.Reflection.BindingFlags that specify
/// how the search is conducted.-or- Zero, to return an empty array.
/// </param>
/// <param name="result">When this method returns, contains array of System.Reflection.MemberInfo with found members or empty (in a case of failure).</param>
/// <exception cref="ArgumentNullException"></exception>
/// <returns>returns true if method with the given data was found; otherwise false.</returns>
public static bool TryGetMember(this Type type, string name, BindingFlags bindingAttr, out MemberInfo[] result)
{
if (type == null)
throw new ArgumentNullException("type");
if (name == null)
throw new ArgumentNullException("name");
result = new MemberInfo[0];
try
{
result = type.GetMember(name, bindingAttr);
}
catch
{
}
return result.Count() != 0;
}
/// <summary>
/// Searches for the public members with the specified name.
/// </summary>
/// <param name="name">The string containing the name of the public members to get.</param>
/// <param name="result">When this method returns, contains array of System.Reflection.MemberInfo with found members or empty (in a case of failure).</param>
/// <exception cref="ArgumentNullException"></exception>
/// <returns>returns true if method with the given data was found; otherwise false.</returns>
public static bool TryGetMember(this Type type, string name, out MemberInfo[] result)
{
return type.TryGetMember(name, DEFAULT_LOOKUP, out result);
}
/// <summary>
/// Searches for the specified property, using the specified binding constraints.
/// </summary>
/// <param name="name">The string containing the name of the property to get.</param>
/// <param name="bindingAttr">
/// A bitmask comprised of one or more System.Reflection.BindingFlags that specify
/// how the search is conducted.-or- Zero, to return null.
/// </param>
/// <param name="result">When this method returns, contains System.Reflection.PropertyInfo of found property or null (in a case of failure).</param>
/// <exception cref="ArgumentNullException"></exception>
/// <returns>returns true if property with the given data was found; otherwise false.</returns>
public static bool TryGetProperty(this Type type, string name, BindingFlags bindingAttr, out PropertyInfo result)
{
if (type == null)
throw new ArgumentNullException("type");
if (name == null)
throw new ArgumentNullException("name");
result = default(PropertyInfo);
try
{
result = type.GetProperty(name, bindingAttr);
}
catch
{
}
return result != default(PropertyInfo);
}
/// <summary>
/// Searches for the public property with the specified name.
/// </summary>
/// <param name="name">The string containing the name of the property to get.</param>
/// <param name="result">When this method returns, contains System.Reflection.PropertyInfo of found property or null (in a case of failure).</param>
/// <exception cref="ArgumentNullException"></exception>
/// <returns>returns true if property with the given data was found; otherwise false.</returns>
public static bool TryGetProperty(this Type type, string name, out PropertyInfo result)
{
return type.TryGetProperty(name, DEFAULT_LOOKUP, out result);
}
/// <summary>
/// Searches for the specified public property whose parameters match the specified
/// argument types.
/// </summary>
/// <param name="name">The string containing the name of the property to get.</param>
/// <param name="returnType">The return type of the property.</param>
/// <param name="types">
/// An array of System.Type objects representing the number, order, and type
/// of the parameters for the indexed property to get.-or- An empty array of
/// the type System.Type (that is, Type[] types = new Type[0]) to get a property
/// that is not indexed.
/// </param>
/// <param name="result">When this method returns, contains System.Reflection.PropertyInfo of found property or null (in a case of failure).</param>
/// <exception cref="ArgumentNullException"></exception>
/// <returns>returns true if property with the given data was found; otherwise false.</returns>
public static bool TryGetProperty(this Type type, string name, Type returnType, Type[] types, out PropertyInfo result)
{
if (type == null)
throw new ArgumentNullException("type");
if (name == null)
throw new ArgumentNullException("name");
if (returnType == null)
throw new ArgumentNullException("returnType");
result = default(PropertyInfo);
try
{
result = type.GetProperty(name, returnType, types);
}
catch
{
}
return result != default(PropertyInfo);
}
/// <summary>
/// Searches for the public property with the specified name and return type.
/// </summary>
/// <param name="name">The string containing the name of the property to get.</param>
/// <param name="returnType">The return type of the property.</param>
/// <param name="result">When this method returns, contains System.Reflection.PropertyInfo of found property or null (in a case of failure).</param>
/// <exception cref="ArgumentNullException"></exception>
/// <returns>returns true if property with the given data was found; otherwise false.</returns>
public static bool TryGetProperty(this Type type, string name, Type returnType, out PropertyInfo result)
{
return type.TryGetProperty(name, returnType, null, out result);
}
/// <summary>
/// Searches for the specified field, using the specified binding constraints.
/// </summary>
/// <param name="name">The string containing the name of the data field to get.</param>
/// <param name="bindingAttr">
/// A bitmask comprised of one or more System.Reflection.BindingFlags that specify
/// how the search is conducted.-or- Zero, to return null.
/// </param>
/// <param name="result">When this method returns, contains System.Reflection.FieldInfo of found data field or null (in a case of failure).</param>
/// <exception cref="ArgumentNullException"></exception>
/// <returns>returns true if data field with the given data was found; otherwise false.</returns>
public static bool TryGetField(this Type type, string name, BindingFlags bindingAttr, out FieldInfo result)
{
if (type == null)
throw new ArgumentNullException("type");
if (name == null)
throw new ArgumentNullException("name");
result = default(FieldInfo);
try
{
result = type.GetField(name, bindingAttr);
}
catch
{
}
return result != default(FieldInfo);
}
/// <summary>
/// Searches for the public field with the specified name.
/// </summary>
/// <param name="name">The string containing the name of the data field to get.</param>
/// <param name="result">When this method returns, contains System.Reflection.FieldInfo of found data field or null (in a case of failure).</param>
/// <exception cref="ArgumentNullException"></exception>
/// <returns>returns true if data field with the given data was found; otherwise false.</returns>
public static bool TryGetField(this Type type, string name, out FieldInfo result)
{
return type.TryGetField(name, DEFAULT_LOOKUP, out result);
}
/// <summary>
/// When overridden in a derived class, returns the System.Reflection.EventInfo
/// object representing the specified event, using the specified binding constraints.
/// </summary>
/// <param name="name">
/// The string containing the name of an event which is declared or inherited
/// by the current System.Type.
/// </param>
/// <param name="bindingAttr">
/// A bitmask comprised of one or more System.Reflection.BindingFlags that specify
/// how the search is conducted.-or- Zero, to return null.
/// </param>
/// <param name="result">When this method returns, contains System.Reflection.EventInfo of found event or null (in a case of failure).</param>
/// <exception cref="ArgumentNullException"></exception>
/// <returns>returns true if event with the given data was found; otherwise false.</returns>
public static bool TryGetEvent(this Type type, string name, BindingFlags bindingAttr, out EventInfo result)
{
if (type == null)
throw new ArgumentNullException("type");
if (name == null)
throw new ArgumentNullException("name");
result = default(EventInfo);
try
{
result = type.GetEvent(name, bindingAttr);
}
catch
{
}
return result != default(EventInfo);
}
/// <summary>
/// Returns the System.Reflection.EventInfo object representing the specified
/// public event.
/// </summary>
/// <param name="name">
/// The string containing the name of an event that is declared or inherited
/// by the current System.Type.
/// </param>
/// <param name="result">When this method returns, contains System.Reflection.EventInfo of found event or null (in a case of failure).</param>
/// <exception cref="ArgumentNullException"></exception>
/// <returns>returns true if event with the given data was found; otherwise false.</returns>
public static bool TryGetEvent(this Type type, string name, out EventInfo result)
{
return type.TryGetEvent(name, DEFAULT_LOOKUP, out result);
}
/// <summary>
/// Searches for the specified method, using the specified binding constraints.
/// </summary>
/// <param name="name">The string containing the name of the method to get.</param>
/// <param name="bindingAttr">
/// A bitmask comprised of one or more System.Reflection.BindingFlags that specify
/// how the search is conducted.-or- Zero, to return null.
/// </param>
/// <param name="result">When this method returns, contains System.Reflection.MethodInfo of found method or null (in a case of failure).</param>
/// <exception cref="ArgumentNullException"></exception>
/// <returns>returns true if method with the given data was found and match is not ambiguous; otherwise false.</returns>
public static bool TryGetMethod(this Type type, string name, BindingFlags bindingAttr, out MethodInfo result)
{
if (type == null)
throw new ArgumentNullException("type");
if (name == null)
throw new ArgumentNullException("name");
result = default(MethodInfo);
try
{
result = type.GetMethod(name, bindingAttr);
}
catch
{
}
return result != default(MethodInfo);
}
/// <summary>
/// Searches for the public method with the specified name.
/// </summary>
/// <param name="name">The string containing the name of the public method to get.</param>
/// <param name="result">When this method returns, contains System.Reflection.MethodInfo of found method or null (in a case of failure).</param>
/// <exception cref="ArgumentNullException"></exception>
/// <returns>returns true if method with the given data was found and match is not ambiguous; otherwise false.</returns>
public static bool TryGetMethod(this Type type, string name, out MethodInfo result)
{
return type.TryGetMethod(name, DEFAULT_LOOKUP, out result);
}
/// <summary>
/// Searches for the specified public method whose parameters match the specified
/// argument types.
/// </summary>
/// <param name="name">The string containing the name of the public method to get.</param>
/// <param name="types">
/// An array of System.Type objects representing the number, order, and type
/// of the parameters for the method to get.-or- An empty array of System.Type
/// objects (as provided by the System.Type.EmptyTypes field) to get a method
/// that takes no parameters.
/// </param>
/// <param name="result">When this method returns, contains System.Reflection.MethodInfo of found method or null (in a case of failure).</param>
/// <exception cref="ArgumentNullException"></exception>
/// <returns>returns true if method with the given data was found; otherwise false.</returns>
public static bool TryGetMethod(this Type type, string name, Type[] types, out MethodInfo result)
{
if (type == null)
throw new ArgumentNullException("type");
if (name == null)
throw new ArgumentNullException("name");
result = default(MethodInfo);
try
{
result = type.GetMethod(name, types);
}
catch
{
}
return result != default(MethodInfo);
}
}
I know that there [almost] always is a reason why such simple and useful (at least, I think so) features are missing. Is there anything wrong (i.e.: some edge-cases that are not handled, leading to bad coding practices, etc.) with this or any other implementation of these methods? Also how can this code improved?