gpt4 book ai didi

c# - 如何将 C# 方法转换为编译表达式?

转载 作者:太空狗 更新时间:2023-10-29 23:12:57 25 4
gpt4 key购买 nike

我有以下类层次结构:

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;
}
}

我需要能够在任何给定时间使用反射为 Child 的新实例调用这些方法中的任何一个,但是为了提高性能,我需要求助于 Delegate和/或编译表达式

例如我可以:

var instanceOne = new Child();
var instanceTwo = new Child();

为此,我需要在运行时调用这些方法,为那些需要它的人传递参数。请注意,它们包括 staticinstance 方法,其中一些方法接受参数。

到目前为止,我已经为“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()

然后:

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

但是我得到:

1-Say
1-Say

代替:

1-Say 
2-Say

我怀疑这是由于 Expression.Constant 造成的,但我不知道如何让它在运行时接受 Child 的实例作为其目标。

当涉及到表达式时,我很绝望:-(

我基本上是在尝试实现 Jon Skeet 提到的 HERE使用 DelegatesCompiled Expressions

非常感谢任何帮助。

最佳答案

如果我没理解错的话,你需要像这样使用参数:

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

当然,这不会输出 1, 2,因为您的 _number 字段是静态的,并且在创建两个实例后,两者的值都为 2。

编辑。如果您需要使用参数调用方法 - 声明更多参数。例如,如果 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");

关于c# - 如何将 C# 方法转换为编译表达式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40852584/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com