[英]How can I convert C# methods to compiled expressions?
I have the following class hierarchy: 我具有以下类层次结构:
public class Parent
{
[DebuggerStepThrough]
public void SayParent()
{
Console.WriteLine("Parent");
}
}
public sealed class Child : Parent
{
private static int _number = 0;
public Child() // May contain parameter i.e. not always parameterless consctructor
{
_number++;
}
[DebuggerStepThrough]
public void SayInstance()
{
Console.WriteLine("{0}-Say", _number);
}
[DebuggerStepThrough]
public void SayInstanceWithArg(string input)
{
Console.WriteLine("{0}-Say: {1}", _number, input);
}
[DebuggerStepThrough]
public static void SayStatic()
{
Console.WriteLine("{0}-Say", _number);
}
[DebuggerStepThrough]
public static void SayStaticWithArg(string input)
{
Console.WriteLine("{0}-Say: {1}", _number, input);
}
[DebuggerStepThrough]
public static Task SayStaticWithArgAndReturn(string input)
{
Console.WriteLine("{0}-Say: {1}", _number, input);
return null;
}
}
I need to be able to invoke any of these methods for a new instance of Child
at any given time using reflection however to improve performance I need to resort to Delegate
and/or Compiled Expressions
. 我需要能够在任何给定时间使用反射为
Child
的新实例调用这些方法中的任何一种,但是为了提高性能,我需要求助于Delegate
和/或Compiled Expressions
。
So for example I can have: 因此,例如,我可以拥有:
var instanceOne = new Child();
var instanceTwo = new Child();
for which I would need to at runtime invoke these methods passing the arguments for those that need it. 为此,我需要在运行时调用这些方法,为需要它的人传递参数。 Note they include both
static
and instance
methods with some accepting a parameter. 请注意,它们包括
static
方法和instance
方法,并带有一些接受参数的方法。
I have so far tried the following for the "SayInstance" method: 到目前为止,我已经为“ SayInstance”方法尝试了以下方法:
var sayInstanceMethod = typeof(Child)
.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)
.Where(m => m.GetCustomAttributes(typeof(DebuggerStepThroughAttribute), true).Length > 0)
.Where(t => t.Name == "SayInstance")
.First()
And then: 然后:
var instance = Expression.Constant(new Child()); // This should NOT be Constant, but then what should it be?!
var mCallInstance = Expression.Call(instance, sayInstanceMethod);
Action action = Expression.Lambda<Action>(mCallInstance).Compile();
action();
action(); // I need to pass in a new instance of Child to this method somehow
However I am getting: 但是我得到:
1-Say
1-Say
instead of: 代替:
1-Say
2-Say
I suspect this is due to Expression.Constant
but I cannot figure out how I could let it accept an instance of Child
as its target at runtime. 我怀疑这是由于
Expression.Constant
引起的,但我无法弄清楚如何让它在运行时接受Child
实例作为其目标。
I am hopeless when it comes to Expressions
:-( 对于
Expressions
我无可救药:-(
I am basically trying to implement what Jon Skeet mentions HERE either using Delegates
or Compiled Expressions
. 我基本上是想实现什么乔恩斯基特提到这里或者使用
Delegates
或Compiled Expressions
。
Any help is very much appreciated. 很感谢任何形式的帮助。
If I understood correctly, you need to use parameters, like this: 如果我理解正确,则需要使用如下参数:
var instanceOne = new Child();
var instanceTwo = new Child();
var instance = Expression.Parameter(typeof(Child), "c"); // This should NOT be Constant, but then what should it be?!
var mCallInstance = Expression.Call(instance, sayInstanceMethod);
Action<Child> action = Expression.Lambda<Action<Child>>(mCallInstance, instance).Compile();
action(instanceOne);
action(instanceTwo); // I need to pass in a new instance of Child to this method somehow
Of course this will not output 1, 2
because your _number field is static and after creation of two instances has value 2 for both. 当然,这不会输出
1, 2
因为您的_number字段是静态的,并且在创建两个实例后,两个实例的值均为2。
EDIT. 编辑。 If you need to call method with arguments - declare more parameters.
如果您需要使用参数调用方法-请声明更多参数。 For example if SayInstance has one argument of type string, then:
例如,如果SayInstance具有一个字符串类型的参数,则:
var instanceOne = new Child();
var instanceTwo = new Child();
var instance = Expression.Parameter(typeof(Child), "instance");
var arg = Expression.Parameter(typeof(string), "arg");
var mCallInstance = Expression.Call(instance, sayInstanceMethod, arg);
Action<Child,string> action = Expression.Lambda<Action<Child,string>>(mCallInstance, instance, arg).Compile();
action(instanceOne, "one");
action(instanceTwo, "two");
Try this out, this workf for me for a parameterless constructor, but this is that you need: 试试这个,对于没有参数的构造函数来说,这对我来说是工作,但这是您需要的:
var instance = Expression.New(typeof(Child).GetConstructor(new Type[0]));
var mCallInstance = Expression.Call(instance, sayInstanceMethod);
Action action = Expression.Lambda<Action>(mCallInstance).Compile();
action();
action(); // I need to pass in a new instance of Child to this method someh
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.