Reflection to Identify Extension Methods

Reflection to Identify Extension Methods

You have to look in all the assemblies where the extension method may be defined.

Look for classes decorated with ExtensionAttribute, and then methods within that class which are also decorated with ExtensionAttribute. Then check the type of the first parameter to see if it matches the type you're interested in.

Here's some complete code. It could be more rigorous (it's not checking that the type isn't nested, or that there is at least one parameter) but it should give you a helping hand.

using System;
using System.Runtime.CompilerServices;
using System.Reflection;
using System.Linq;
using System.Collections.Generic;

public static class FirstExtensions
{
public static void Foo(this string x) {}
public static void Bar(string x) {} // Not an ext. method
public static void Baz(this int x) {} // Not on string
}

public static class SecondExtensions
{
public static void Quux(this string x) {}
}

public class Test
{
static void Main()
{
Assembly thisAssembly = typeof(Test).Assembly;
foreach (MethodInfo method in GetExtensionMethods(thisAssembly,
typeof(string)))
{
Console.WriteLine(method);
}
}

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;
}
}

Using reflection to check if a method is Extension Method

Based on

F# extension methods in C#

it seems there is an attribute on the compiled form. So see if the method has this attribute:

http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.extensionattribute.aspx

How to use reflection to get extension method on generic type

The problem is that extension methods don't modify the type they are 'extending'. What actually happens behind the scenes is that the compiler transparently translates all the calls that seem to be made on the object in question to calls to your static method.

ie.

int? input = new int?().TryParseNullable("12345");
// becomes...
int? input = YourClass.TryParseNullable(new int?(), "12345");

From there it becomes obvious why it's not showing up via reflection. This also explains why you have to have a using directive for the namespace where YourClass is defined for the extension methods to be visible to the compiler. As to how you can actually get at that information, I'm not sure there is a way, short of running over all the declared types (perhaps a filtered list of interesting classes, if you know that sort of information at compile time) looking for static methods with the ExtensionMethodAttribute ([ExtensionMethod]) defined on them, then trying to parse the MethodInfo for the parameter list to work out if they work on Nullable<>.

How to call a generic extension method with reflection?

The extension method isn't attached to the type Form, it's attached to the type MyClass, so grab it off that type:

MethodInfo methodInfo = typeof(MyClass).GetMethod("GenericExtension",
new[] { typeof(Form), typeof(string) });

How to use C# reflection to invoke an extension method with generic List parameter?

The type that you need to pass to MakeGenericMethod is string, not List<string>, because the parameter is used as T.

var mi = typeof(Extensions).GetMethod("List");
var stringGeneric = mi.MakeGenericMethod(typeof(string));
stringGeneric.Invoke(null, new object[] {new List<string> { "list of string"} });

Otherwise, you are making a method that accepts a list of lists of strings.

Extension method and reflection

Extension methods are just syntactic sugar to make your code look better. The only thing to remember is that they are actually static members of the static class, not methods on the type they are extending. Performance wise, invoking them through reflection is no different from invoking any other static method.

static class MyExtensions
{
public static void Foo(this int i)
{
// do something
}
}

var methodInfo = typeof(MyExtensions).GetMethod("Foo");
methodInfo.Invoke(null, new object[] { 1 });

Reflection returning extension methods that aren't defined

While your application targets framework version 4.6 all that means is thats the minimum version of the framework it can run against. This targeting essentially tells the compiler what 'APIs' are available when you developing and when you compile your program but remember reflection has no compile time safety. It just does what you tell it at run time and you hope it works.

In your example the framework version your are running on (not targeting) is 4.7.2. I know this because you found a method via reflection that is only present on 4.7.2

Reflection on enum extension method located in separate assembly

Extension methods are just static methods, compiler translates this call

yourEnum.Test();

to:

MyClass.Test(yourEnum);

So in order to get Test method info via reflection, you need to inspect MyClass, ActivityStatus is just a parameter there.

var testMethodInfo = typeof(MyClass).GetMethod("Test");
var firstParameter = testMethodInfo.GetParameters()[0];

Console.WriteLine (firstParameter.ParameterType + " " + firstParameter.Name);

prints:

ActivityStatus _value

If you want to get all extension methods for type in a particular assembly, you can use next code:

var extensionMethodsForActivityStatus = 
typeof(ActivityStatus) //type from assembly to search
.Assembly //pick an assembly
.GetTypes() //get all types there
.SelectMany(t => t.GetMethods()) //get all methods for that type
.Where(m => m.GetParameters().Any() &&
m.GetParameters().First().ParameterType == typeof(ActivityStatus)) //check if first parameter is our enum
.Where(m => m.IsDefined(typeof(ExtensionAttribute), true)); //check if the method is an extension method

foreach(var extensionMethod in extensionMethodsForActivityStatus)
Console.WriteLine(extensionMethod.Name); //prints only Test


Related Topics



Leave a reply



Submit