在不使用静态类的情况下调用类的扩展方法,而是通过使用反射使用类iteslf

时间:2018-12-24 03:17:13

标签: c# reflection extension-methods

我想使用MyClass类型调用Method2,它是MyClass的扩展方法。我想知道这是否可能。

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();

        }

    }
}

2 个答案:

答案 0 :(得分:3)

实际上,有一种解决方法,但是有点困难。如果您不忘记在扩展方法参数中放置一个this关键字,C#编译器将向该方法和此类发出ExtensionAttribute。知道了这一点,您便可以找到此扩展方法并执行它:

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

如果不确定在哪个程序集中搜索扩展方法,则可以尝试搜索全部

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

请注意:反射速度。真的很慢即使您使用.Where(type => type.IsSealed)或其他任何过滤器过滤了所有类型,它仍然非常慢。如果您还有其他方法可以在扩展方法中调用代码,则可能应该使用该方法。

答案 1 :(得分:1)

当然,唯一的警告是。NetReflection 无法理解this扩展方法语法糖。

请记住,扩展方法是一种C#构造,当在给定第一个参数(标有this关键字)的情况下调用静态类static方法时,可以为您节省几个可打印字符 em>

因此,在短期内,您必须定位静态类,并将MyClass实例作为第一个参数传递

var myClass = new MyClass();

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

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

输出

You have called ex Method 2

Full Demo Here

更新

  

我不想使用typeof(MyClassStatic)..我想使用   typeof(MyClass)

Method2不是MyClass的成员,并且您不能以我能想到的任何方式强迫它是如此。