在不使用静态 class 的情况下调用 class 的扩展方法,而是通过使用 class 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();
}
}
}
当然有可能,唯一需要注意的是 .Net Reflection 不理解 Extension Method 语法糖 this
.
请记住,扩展方法是一种 C# 结构,在给定第一个参数(标有 this
关键字)
简而言之,您必须以静态 class 为目标并将 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
更新
I dont want to use typeof(MyClassStatic).. I want to use
typeof(MyClass)
Method2
不是 MyClass
的成员,您不能以我能想到的任何方式强制它成为成员。
这个其实是有办法的,就是有点难。如果您没有忘记将 this
关键字放置到您的扩展方法参数中,C# 编译器将向此方法和此 class 发送 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)
或任何其他过滤器过滤所有类型,它仍然 非常慢 。如果您有任何其他方式来调用扩展方法中的代码,您可能应该使用这种方式。
我想调用 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();
}
}
}
当然有可能,唯一需要注意的是 .Net Reflection 不理解 Extension Method 语法糖 this
.
请记住,扩展方法是一种 C# 结构,在给定第一个参数(标有 this
关键字)
简而言之,您必须以静态 class 为目标并将 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
更新
I dont want to use typeof(MyClassStatic).. I want to use typeof(MyClass)
Method2
不是 MyClass
的成员,您不能以我能想到的任何方式强制它成为成员。
这个其实是有办法的,就是有点难。如果您没有忘记将 this
关键字放置到您的扩展方法参数中,C# 编译器将向此方法和此 class 发送 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)
或任何其他过滤器过滤所有类型,它仍然 非常慢 。如果您有任何其他方式来调用扩展方法中的代码,您可能应该使用这种方式。