【问题标题】:Invoke instance method statically静态调用实例方法
【发布时间】:2015-09-14 05:27:52
【问题描述】:

假设有一个类A 带有无参数实例方法

class A
{
    public A(int x) { this.x = x; }
    private int x;
    public int foo() { return x; }
}

使用反射很容易调用方法:

A a = new A(100);
var method = typeof(A).GetMethod("foo");
var result = method.Invoke(a, new object[0]); // 100

但是,我想像调用静态方法一样调用该方法

var staticmethod = Something(typeof(A), "foo");
var result = staticmethod.Invoke(null, new object[] { a });

有什么办法可以得到这个staticmethod

注意:我希望Something 是通用的,即A 可以是任何类,foo 可以是任何实例方法。

编辑:说清楚:

A 类中没有静态方法。

有一个无参数的实例方法称为foo

我想调用(使用MethodInfo.Invokefoo AS IF 它是一个静态方法,以类A 作为参数。

EDIT2:为什么我想要这个:(帮助您更好地理解)

我有一个静态方法列表,它们对不同类型执行类似的工作,它们存储在字典 Dictionary<Type, MethodInfo> dict 中。

因此,每当我有一个对象obj 并想做这项工作时,我都可以

dict[obj.GetType()].Invoke(null, new object[] { obj, param1, param2, ... });

现在我也想在其中添加实例方法,但这需要我记住哪些方法是静态的,哪些方法是实例绑定的,并以不同的方式调用它们:

dict[obj.GetType()].Invoke(null, new object[] { obj, param1, param2, ... }); // static methods
dict[obj.GetType()].Invoke(obj, new object[] { param1, param2, ... }); // instance methods

这很不方便。所以我想从实例方法中获取静态MethodInfo,然后再将它们添加到字典中。

EDIT3:我不明白为什么这个问题被标记为重复。链接页面没有回答我的问题。如果我遗漏了什么,请告诉我。

链接页面有几个答案,但它们要么

  1. 要求我知道foo 需要多少个参数,或者
  2. 提供了一个以object[] 作为参数的方法,而不是参数列表。

所以它们都不适合这里。

经过一番研究,我发现有些东西接近我需要的东西:

 A a = new A(100);
 var method = typeof(A).GetMethod("foo");
 var deleg = Delegate.CreateDelegate(typeof(Func<A, int>), method)
 var result = deleg.DynamicInvoke(new object[] { a }); // 100

这里,它以new object[] { a } 作为参数。但问题是,由于我不知道 foo 长什么样,我如何传递Delegate.CreateDelegate 的第一个参数?

上次编辑:自己找到了解决方案。谢谢你们的帮助!

【问题讨论】:

  • 您可以使用第一个方法调用静态方法。在静态方法的情况下,Invoke 的第一个参数被忽略。
  • @Donnie 我不认为他想调用静态方法。他尝试像静态方法一样调用实例方法。
  • @Donnie 我不想调用静态方法,我想要的是使用第二种方法调用实例方法
  • 像调用静态方法一样调用方法 这到底是什么意思?您尝试调用的方法实际上是静态的还是您根本不想创建 A 的实例?
  • Here's an example 你可以做的一件事

标签: c# reflection


【解决方案1】:

但这需要我记住哪些方法是静态的,哪些方法是实例绑定的,并以不同的方式调用它们

不需要记住它,因为方法自己知道这一点:

MethodInfo mi = GetTheMethodFromSomewhere();
object[] args = new object[] { obj, param1, param2, … };
if (mi.IsStatic)
    mi.Invoke(null, args);
else
    mi.Invoke(args[0], args.Skip(1).ToArray());

【讨论】:

  • 这正是我不想要的......你正在以不同的方式调用它们
  • 好吧,如果不以不同的方式调用它们,你无法做到这一点。它们必须以不同的方式调用,因为它们根本不同。您想出的所有其他方式(如DynamicInvoke)也会以某种方式封装不同的调用。
  • 好吧,我不是在谈论调用方法的底层机制,而是如何通过代码调用方法——我的答案看起来还不错。顺便说一句,我真的怀疑底层机制不同,它只是一个隐含的“this”第一个参数
  • 我的意思是,因为我会调用很多方法,所以我需要做任何事情来简化调用代码——我不想写这个 if-else 一千次,所以我在添加这些方法时,必须想出一种方法来统一事物。在我的情况下,编写另一种方法来封装调用时的差异是不行的(尽管在我的回答中是可能的)
  • @MichaelKim DynamicInvoke 可能看起来不错,但 it’s really not。您拥有决定是否需要静态调用该方法所需的所有信息。通过创建动态委托来采取额外的路线只会给运行时增加很多不必要的额外负担。您还没有给出分支调用会成为问题的单一原因,如果您只是将其包装在一个方法中,那么 使用 它没有区别;但你会获得更好的性能。
【解决方案2】:

静态方法和实例方法可以通过创建委托,然后调用DynamicInvoke来统一:

Dictionary<Type, Delegate> dict = new Dictionary<Type, Delegate>();

void AddMethod(Type type, String methodName)
{
    var method = type.GetMethod(methodName);
    var types = method.GetParameters().ConvertAll(p => p.ParameterType).ToList();
    if (!method.IsStatic)
        types.Insert(0, type);
    types.Add(method.ReturnType);
    var delegType = Expression.GetFuncType(types.ToArray());
    var deleg = method.CreateDelegate(delegType);
    dict.Add(type, deleg);
}

object GetJobResult(object obj, params object[] additionalParams)
{
    var paramList = additionalParams.ToList();
    paramList.Insert(0, obj);
    return dict[obj.GetType()].DynamicInvoke(paramList.ToArray());
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-10
    • 1970-01-01
    • 2012-11-12
    • 2020-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多