using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Chernobyl.Attribution;
using Chernobyl.Collections.Generic;
using Chernobyl.Reflection;
namespace Chernobyl.Extensions
{
///
/// Extensions and utility methods for and
/// related types.
///
public static class KeyAttribute
{
///
/// Retrieves the values of the parameter using the find method provided.
///
/// The parameter to locate values for.
/// The method used to locate the parameters.
/// The method to invoke when the parameters have
/// been found.
public static void GetValues(this ParameterInfo parameter,
Find find,
Callback> callback)
{
find.FindMany(parameter.GetKeys(), callback);
}
///
/// Retrieves the value of the parameter using the find method provided.
///
/// The parameter to locate value for.
/// The method used to locate the parameter.
/// The method to invoke when the parameters have
/// been found.
public static void GetValue(this ParameterInfo parameter,
Find find,
Callback callback)
{
parameter.GetValues(find, values =>
{
values.Duplicated()
.DefaultIfEmpty(values.First)
.To(callback.AsAction());
});
}
///
/// Retrieves the values of the parameters using the find method provided.
///
/// The parameters to locate values for.
/// The method used to locate the parameters.
/// The method to invoke when the parameters have
/// been found.
public static void GetValues(this IEnumerable parameters,
Find find,
Callback> callback)
{
find.FindMany(parameters, callback);
}
///
/// Returns the static, void return methods that are attributed with a
/// .
///
/// The type to look in for the methods.
/// The static, void return methods mapped to their keys.
public static IEnumerable> GetActions(this Type type)
{
Func>> selector =
method => method.GetCustomAttributes(typeof(IKeyAttribute), true)
.Cast()
.Select(attr => new KeyValuePair(
attr.Key, () => method.Invoke(null, Array.Empty)));
// Grab static methods that have no parameters.
return type.GetMethods()
.Where(method => method.IsStatic &&
method.GetParameters().IsEmpty() &&
method.ReturnType == typeof(void))
.SelectMany(selector);
}
///
/// Returns the static, void return methods that are attributed with a
/// .
///
/// The to look in for the
/// methods.
/// The static, void return methods mapped to their keys.
public static IEnumerable> GetActions(this Assembly assembly)
{
return assembly.GetTypes().SelectMany(type => type.GetActions());
}
///
/// Retrieves methods that provide the callback with the return values of
/// any static, parameterless methods whose return value has been mapped
/// to keys using and returns the value.
///
/// The to search for keyed values.
/// The items held in methods mapped to the keys.
public static IEnumerable>>> GetLocators(
this Type type)
{
IDictionary>> items =
new Dictionary>>();
// Grab static methods that have no parameters.
var staticMethods = type.GetMethods()
.Where(method => method.IsStatic &&
method.GetParameters().IsEmpty() &&
method.ReturnType != typeof(void));
// Go through the methods and add them to the dictionary.
foreach (var method in staticMethods)
{
var keyAttribute = (IKeyAttribute)method.ReturnParameter
.GetCustomAttribute(typeof(IKeyAttribute), true);
if (keyAttribute != null)
{
var methodInfo = method;
items.Add(keyAttribute.Key,
callback => callback(methodInfo.Invoke(null, Array.Empty)));
}
}
return items;
}
///
/// Retrieves methods that provide the callback with the return values of
/// any static, parameterless methods whose return value has been mapped
/// to keys using and returns the value.
///
/// The to search for keyed
/// values.
/// The items held in methods mapped to the keys.
public static IEnumerable>>> GetLocators(
this Assembly assembly)
{
return assembly.GetTypes().SelectMany(type => type.GetLocators());
}
///
/// Retrieves methods that, when invoked, invoke any
/// static, parameterless methods whose return value has been mapped to
/// keys using and returns the value.
///
/// The to search for keyed values.
/// The items held in methods mapped to the keys.
public static IEnumerable>> GetKeyedValues(
this Type type)
{
IDictionary> items =
new Dictionary>();
// Grab static methods that have no parameters.
var staticMethods = type.GetMethods()
.Where(method => method.IsStatic &&
method.GetParameters().IsEmpty() &&
method.ReturnType != typeof(void));
// Go through the methods and add them to the dictionary.
foreach (var method in staticMethods)
{
var keyAttribute = (IKeyAttribute)method.ReturnParameter
.GetCustomAttribute(typeof(IKeyAttribute), true);
if (keyAttribute != null)
{
var methodInfo = method;
items.Add(keyAttribute.Key,
() => methodInfo.Invoke(null, Array.Empty));
}
}
return items;
}
///
/// Retrieves methods that, when invoked, invoke any
/// static, parameterless methods whose return value has been mapped to
/// keys using and returns the value.
///
/// The to search for keyed
/// values.
/// The items held in methods mapped to the keys.
public static IEnumerable>> GetKeyedValues(this Assembly assembly)
{
return assembly.GetTypes().SelectMany(type => type.GetKeyedValues());
}
///
/// Retrives the keys that have been attributed on the
/// using the
/// .
///
/// The instance attributed with
/// .
public static IEnumerable GetKeys(this ICustomAttributeProvider provider)
{
return provider.GetCustomAttributes(true)
.Select(attr => attr.Key);
}
}
}