简体   繁体   中英

invoke the extension method of a class without using static class but by using class iteslf using reflection

I want invoke Method2 which is an extension method of a MyClass using MyClass type. I am wondering if this is possible or not.

using System;
using System.Linq;
using System.Reflection;

namespace ConsoleApplication9
{
    public static class MyClassStatic
    {
        public static void Method2(this ConsoleApp2.MyClass obj)
        {
            Console.WriteLine("You have called ex Method 2");
        }
    }

    public interface IClass
    {
        void Method1();
    }

    public class MyClass : ConsoleApp2.IClass
    {
        public void Method1()
        {
            Console.WriteLine("You have called Method 1");
        }
    }

    class Program
    {


        public static void CallWhereMethod()
        {


            var whereMethods = typeof(MyClass)
                .GetMethods(BindingFlags.Static | BindingFlags.Public)
                .Where(mi => mi.Name == "Method2");


            Console.WriteLine(whereMethods.Count());
            // returns zero

        }

        static void Main(string[] args)
        {
            CallWhereMethod();
            Console.ReadKey();

        }

    }
}

Actually, there is a way for this, but it's hard a bit. If you don't forget to place a this keyword to your extension method parameter, C# compiler will emmit ExtensionAttribute to this method and this class. Knowing this, you are able to find this extension method and execute it:

var myClassType = typeof(MyClass);
var myClass = new MyClass();

var assemblyTypes = Assembly.GetExecutingAssembly().GetTypes();
foreach (var type in assemblyTypes.Where(t => t.GetCustomAttribute<ExtensionAttribute>() != null)
{
    var typeMethods = type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
    foreach (var method in typeMethods.Where(m => m.IsDefined(typeof(ExtensionAttribute), inherit: false))
    {
        if (method.GetParameters()[0].ParameterType == myClassType)
        {
            // here you go
            method.Invoke(null, new object[]{ myClass });
        }
    }
}

If you unsure in which assembly to search for extension method, you may try to search all :

var allLoadedTypes = AppDomain.CurrentDomain.GetAssemblies().SelectMany(a => a.GetTypes());

Please note: reflection is slow . Really slow. Even you filter all of your types with .Where(type => type.IsSealed) or any other filter, it is still dead slow . If you have any other way to invoke the code in your extension method, you probably should use that way.

Sure its possible, the only caveat is .Net Reflection doesn't understand the Extension Method syntactic-sugar of this .

Remembering, that an extension method is a C# construct to save you a couple of printable-characters when calling a static class static method when given the first parameter (labelled with the this keyword)

So in-Short, you'll have to target the static class and pass in the MyClass instance as the first parameter

var myClass = new MyClass();

var whereMethods = typeof(MyClassStatic)
                  .GetMethods(BindingFlags.Static | BindingFlags.Public)
                  .FirstOrDefault(mi => mi.Name == "Method2");

whereMethods.Invoke(null, new object[]{ myClass } );

Output

You have called ex Method 2

Full Demo Here

Update

I dont want to use typeof(MyClassStatic).. I want to use typeof(MyClass)

Method2 is not a member of MyClass , and you cant force it to be as such in any way that i can think of.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM