如果我有一个 Expression<Func<Delegate>>
形式的表达式是否可以确定用于传递委托(delegate)的对象的派生类型?该表达式是否包含此信息,或者它是否唯一代表委托(delegate)。
代码示例应该会让事情变得更清楚。
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
namespace Sandbox {
public interface IContract {
void Method();
}
public class Concrete : IContract {
public void Method() { }
}
public class Test {
private IContract contract = new Concrete();
private Concrete concrete = new Concrete();
public static string GetFullMethodName(Expression<Func<Action>> expression) {
var unaryExpression = (UnaryExpression)expression.Body;
var methodCallExpression = (MethodCallExpression)unaryExpression.Operand;
var methodInfoExpression = (ConstantExpression)methodCallExpression.Arguments.Last();
var methodInfo = (MemberInfo)methodInfoExpression.Value;
var type = methodInfo.DeclaringType;
var name = methodInfo.Name;
return String.Format("{0}.{1}", type, name);
}
public Test() {
var strConcrete = GetFullMethodName(() => concrete.Method); // Sandbox.Concrete.Method
var strContract = GetFullMethodName(() => contract.Method); // Sandbox.IContract.Method
}
}
}
是否可以制作 () => contract.Method
生产
Sandbox.Concrete.Method
而不是
Sandbox.IContract.Method
是否可以更改表达式以支持这一点,或者我是否会被迫将对象的实例作为单独的参数传递以确定其类型?
最佳答案
不,这是不可能的。
表达式树是根据编译时信息构建的,在编译时,被调用的方法是虚拟的IContract.Method
。事实上,在运行时,Concrete.Method
实际被调用是无关紧要的 - 这是在虚拟调度机制中处理的,并且编译器早在任何决定之前就完成了它的工作。
您能做的最好的事情就是尝试自己模拟虚拟调度。例如,您可以尝试在运行时枚举 this
实例上的接口(interface)实现,如果您确实找到与该接口(interface)匹配的方法,则将返回该方法。然而,这确实很棘手 - 您需要能够完美模拟实际的虚拟调度。
另一个棘手的问题是你尝试获取值的方式已经被破坏了。例如,在我的环境中,methodInfoExpression
不是一个ConstantExpression
- 它是闭包类型上的一个字段。你的“解析”非常脆弱。
也就是说,这也是不必要和过于复杂的 - 您试图接收一个返回操作的表达式,并从表达式中“窃取”操作的值。已经有一个简单的方法可以做到这一点 - 直接传递该参数。无需将其隐藏在表达式树中:
public static string GetFullMethodName(Action action)
{
return string.Format("{0}.{1}", action.Method.DeclaringType.Name, action.Method.Name);
}
var strConcrete = GetFullMethodName(concrete.Method).Dump(); // Sandbox.Concrete.Method
var strContract = GetFullMethodName(contract.Method).Dump(); // Sandbox.Concrete.Method
你不需要表达基本反射已经给你的东西:)
关于c# - 从方法表达式获取具体类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36862237/