簡體   English   中英

在不使用靜態類的情況下調用類的擴展方法,而是通過使用反射使用類iteslf

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

我想調用Method2,這是使用MyClass類型的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();

        }

    }
}

實際上,有一種解決方法,但這有點困難。 如果您不忘記在擴展方法參數中放置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)或任何其他過濾器過濾所有類型,它仍然非常 如果您有其他方法可以調用擴展方法中的代碼,則可能應該使用該方法。

當然它的可能,唯一需要注意的是NET反射不理解的擴展方法的語法糖this

記住,擴展方法是一種C#構造,可以在給定第一個參數(標有this關鍵字)的情況下調用static類static方法時為您節省幾個可打印字符。

因此,在短時間內,您必須以靜態類為目標,並將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

完整演示在這里

更新資料

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

Method2不是MyClass的成員,您不能以我能想到的任何方式強迫它是這樣的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM