The reason why your extension method does not get called is because extension methods belong to types where they are defined so such calls:
"Hello world".MyExtensionMethod()
under the hood gets converted to:
ExtensionMethods.MyExtensionMethod("Hello world"));// "Hello world".MyExtensionMethod()
This topic has some code example how to get all the extension methods for specific class, I've extended the code a bit and here's the code for running extension method by name:
// the utility code
internal static class ExtensionMethodsHelper
{
private static readonly ConcurrentDictionary<Type, IDictionary<string, MethodInfo>> methodsMap = new ConcurrentDictionary<Type, IDictionary<string, MethodInfo>>();
[MethodImpl(MethodImplOptions.Synchronized)]
public static MethodInfo GetExtensionMethodOrNull(Type type, string methodName)
{
var methodsForType = methodsMap.GetOrAdd(type, GetExtensionMethodsForType);
return methodsForType.ContainsKey(methodName)
? methodsForType[methodName]
: null;
}
private static IDictionary<string, MethodInfo> GetExtensionMethodsForType(Type extendedType)
{
// WARNING! Two methods with the same name won't work here
// for sake of example I ignore this fact
// but you'll have to do something with that
return AppDomain.CurrentDomain
.GetAssemblies()
.Select(asm => GetExtensionMethods(asm, extendedType))
.Aggregate((a, b) => a.Union(b))
.ToDictionary(mi => mi.Name, mi => mi);
}
private static IEnumerable<MethodInfo> GetExtensionMethods(Assembly assembly, Type extendedType)
{
var query = from type in assembly.GetTypes()
where type.IsSealed && !type.IsGenericType && !type.IsNested
from method in type.GetMethods(BindingFlags.Static
| BindingFlags.Public | BindingFlags.NonPublic)
where method.IsDefined(typeof(ExtensionAttribute), false)
where method.GetParameters()[0].ParameterType == extendedType
select method;
return query;
}
}
// example: class with extension methods
public static class ExtensionMethods
{
public static string MyExtensionMethod(this string myString)
{
return "ranextension on string '" + myString + "'";
}
}
// example: usage
internal class Program
{
private static void Main()
{
var mi = ExtensionMethodsHelper.GetExtensionMethodOrNull(typeof(string), "MyExtensionMethod");
if (mi != null)
{
Console.WriteLine(mi.Invoke(null, new object[] { "hello world" }));
}
else
{
Console.WriteLine("did't find extension method with name " + "MyExtensionMethod");
}
}
}
Update
Let's take this piece of code:
myTest.HasMethodOrExtensionMethod("MyExtensionMethod") ? myTest.MyExtensionMethod() :
"didnotrun"
It does not compile. How to get it working.
// utility code
public static class ExtensionMethods
{
public static string MyExtensionMethod(this string myString)
{
return "ranextension on string '" + myString + "'";
}
public static object InvokeExtensionMethod(this object instance, string methodName, params object[] arguments)
{
if (instance == null) throw new ArgumentNullException("instance");
MethodInfo mi = ExtensionMethodsHelper.GetExtensionMethodOrNull(instance.GetType(), methodName);
if (mi == null)
{
string message = string.Format("Unable to find '{0}' extension method in '{1}' class.", methodName, instance);
throw new InvalidOperationException(message);
}
return mi.Invoke(null, new[] { instance }.Concat(arguments).ToArray());
}
}
// example usage
Console.WriteLine("hey".InvokeExtensionMethod("MyExtensionMethod"));