【问题标题】:How can I invoke a method on an instance using MSIL *without* having a MethodInfo?如何在没有 MethodInfo 的情况下使用 MSIL *调用实例上的方法?
【发布时间】:2012-09-20 03:14:54
【问题描述】:

我有一个遵循特定约定的类的数字属性。例如。

Person1 { get; set; }
Person2 { get; set; }
Person3 { get; set; }

我不想在类的实例上获取MethodInfo 对象,而是做这样的事情:

...
il.Emit(OpCodes.Callvirt, [instance]["set_Person" + index]);

上面的代码行是说明性的,并不是我认为的。

有谁知道我怎么能做到这一点?

【问题讨论】:

  • 使用 DynamicMethod 类。在 MSDN Library 文章中有关于如何使用它的很好的文档。
  • 索引从何而来?是您正在创建的方法的参数吗?还是应该在那种方法中保持不变?
  • @svick:“索引”来自 DynamicMethod 创建者中的 for 循环。
  • 那么你为什么不想得到MethodInfo?这不会对生成代码的性能产生任何影响。
  • 不,不会。在这种情况下,运行时没有MethodInfo

标签: c# reflection dynamic-programming cil


【解决方案1】:

它无法完成,我不明白这一点或任何潜在的好处。 MSIL Callvirt 指令不采用描述要调用什么的字符串,它采用指向特定类型的特定方法的元数据标记,通过反射获取该值的唯一方法是使用 MethodInfo 实例。

这看起来真的不是一个复杂的选择:

il.Emit(OpCodes.Callvirt, type.GetMethod("set_Person" + index));

【讨论】:

  • 我问这个问题的原因是出于性能原因。如果我不必使用反射 1000 次,我相信我会获得一些速度。感谢您的评论。
  • 1000 次对用户来说是完全察觉不到的。如果您正在发出 IL,您应该缓存生成的方法或类并重用它们,而不是每次调用方法时都发出 IL,因此性能优势将为零。此外,如果您发出 IL,您通常会调用静态链接代码中不存在的方法,即动态发现的方法或其他 IL 发出的方法,您可以将其作为 MethodInfo 对象传递。
  • 也就是说,如果您搜索它,就会有很多与typeof(SomeClass) 类似的构造请求,例如:methodof(SomeClass.SomeMethod)fieldof(SomeClass._someField)propertyof(SomeClass.SomeProperty) 等...但我不会让你屏住呼吸,CLR 团队不认为这些是高优先级项目。
【解决方案2】:
public class Sample
{
    public int Person1 { get; set; }
    public int Person2 { get; set; }
    public int Person3 { get; set; }
}

static void Main(string[] args) {
    var s = new  Sample();
    var tuples = new List<Tuple<string, int>> { 
                    Tuple.Create("Person1", 1), 
                    Tuple.Create("Person2", 2), 
                    Tuple.Create("Person3", 3) 
                 };

    var argument = Expression.Constant(s);

    foreach (var item in tuples) {
        CreateLambda(item.Item1, argument, item.Item2)
               .Compile()
               .DynamicInvoke();
    }
 }

static LambdaExpression CreateLambda(string propertyName, Expression instance, int value) {
     return Expression.Lambda(
               Expression.Assign(
                  Expression.PropertyOrField(instance, propertyName), 
                  Expression.Constant(value)));
 }

【讨论】:

  • 这看起来不错,但不是我想要的。 :) 让我试试看。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-07
  • 2021-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多