如何获取作为 func 传递的匿名方法的参数值?
How can i get the parameter values of an anonymous method passed as a func?
我正在远程系统上调用方法。远程系统实现了一个接口,两个系统都有一个副本(通过共享的 nuget 存储库)。目前我正在发送这样的请求:
var oldRequest = new FooRequest("GetEmployeeById", new object[] { "myPartner", 42, DateTime.Now.AddDays(-1) });
界面如下:
public class FooResponse<T> { }
public interface IFooController
{
FooResponse<string> GetEmployeeById(string partnerName, int employeeId, DateTime? ifModifiedSince);
}
正如您所想象的那样,有时程序员在构造函数中以错误的顺序将参数传递给数组,结果开始失败。为了解决这个问题,我创建了以下代码以在创建 FooRequest
:
时获得智能感知支持
public static FooRequest Create<T>(Func<FooResponse<T>> func)
{
return new FooRequest(null, null); // Here goes some magic reflection stuff instead of null.
}
现在可以像这样创建 FooRequest
:
public static IFooController iFooController => (IFooController)new object();
public static FooRequest CreateRequest<T>(Func<FooResponse<T>> func)
{
return FooRequest.Create(func);
}
var newRequest = CreateRequest(() => iFooController.GetEmployeeById("myPartner", 42, DateTime.Now.AddDays(-1)));
那么我的问题是:我如何才能在 FooRequest.Create
-method 中获取方法的名称和参数的值?
我已经用尽了我的反思和 google 技能来寻找价值,但到目前为止运气不好。
如果有人想试一试,可以在这里找到完整的编译代码:http://ideone.com/ovWseI
下面是如何使用表达式执行此操作的草图:
public class Test {
public static IFooController iFooController => (IFooController) new object();
public static FooRequest CreateRequest<T>(Expression<Func<FooResponse<T>>> func) {
return FooRequest.Create(func);
}
public static void Main() {
var newRequest = CreateRequest(() => iFooController.GetEmployeeById("myPartner", 42, DateTime.Now.AddDays(-1)));
Console.ReadKey();
}
}
public class FooRequest {
public static FooRequest Create<T>(Expression<Func<FooResponse<T>>> func) {
var call = (MethodCallExpression) func.Body;
var arguments = new List<object>();
foreach (var arg in call.Arguments) {
var constant = arg as ConstantExpression;
if (constant != null) {
arguments.Add(constant.Value);
}
else {
var evaled = Expression.Lambda(arg).Compile().DynamicInvoke();
arguments.Add(evaled);
}
}
return new FooRequest(call.Method.Name, arguments.ToArray());
}
public FooRequest(string function, object[] data = null) {
//SendRequestToServiceBus(function, data);
Console.Write($"Function name: {function}");
}
}
public class FooResponse<T> {
}
public interface IFooController {
FooResponse<string> GetEmployeeById(string partnerName, int employeeId, DateTime? ifModifiedSince);
}
我正在远程系统上调用方法。远程系统实现了一个接口,两个系统都有一个副本(通过共享的 nuget 存储库)。目前我正在发送这样的请求:
var oldRequest = new FooRequest("GetEmployeeById", new object[] { "myPartner", 42, DateTime.Now.AddDays(-1) });
界面如下:
public class FooResponse<T> { }
public interface IFooController
{
FooResponse<string> GetEmployeeById(string partnerName, int employeeId, DateTime? ifModifiedSince);
}
正如您所想象的那样,有时程序员在构造函数中以错误的顺序将参数传递给数组,结果开始失败。为了解决这个问题,我创建了以下代码以在创建 FooRequest
:
public static FooRequest Create<T>(Func<FooResponse<T>> func)
{
return new FooRequest(null, null); // Here goes some magic reflection stuff instead of null.
}
现在可以像这样创建 FooRequest
:
public static IFooController iFooController => (IFooController)new object();
public static FooRequest CreateRequest<T>(Func<FooResponse<T>> func)
{
return FooRequest.Create(func);
}
var newRequest = CreateRequest(() => iFooController.GetEmployeeById("myPartner", 42, DateTime.Now.AddDays(-1)));
那么我的问题是:我如何才能在 FooRequest.Create
-method 中获取方法的名称和参数的值?
我已经用尽了我的反思和 google 技能来寻找价值,但到目前为止运气不好。
如果有人想试一试,可以在这里找到完整的编译代码:http://ideone.com/ovWseI
下面是如何使用表达式执行此操作的草图:
public class Test {
public static IFooController iFooController => (IFooController) new object();
public static FooRequest CreateRequest<T>(Expression<Func<FooResponse<T>>> func) {
return FooRequest.Create(func);
}
public static void Main() {
var newRequest = CreateRequest(() => iFooController.GetEmployeeById("myPartner", 42, DateTime.Now.AddDays(-1)));
Console.ReadKey();
}
}
public class FooRequest {
public static FooRequest Create<T>(Expression<Func<FooResponse<T>>> func) {
var call = (MethodCallExpression) func.Body;
var arguments = new List<object>();
foreach (var arg in call.Arguments) {
var constant = arg as ConstantExpression;
if (constant != null) {
arguments.Add(constant.Value);
}
else {
var evaled = Expression.Lambda(arg).Compile().DynamicInvoke();
arguments.Add(evaled);
}
}
return new FooRequest(call.Method.Name, arguments.ToArray());
}
public FooRequest(string function, object[] data = null) {
//SendRequestToServiceBus(function, data);
Console.Write($"Function name: {function}");
}
}
public class FooResponse<T> {
}
public interface IFooController {
FooResponse<string> GetEmployeeById(string partnerName, int employeeId, DateTime? ifModifiedSince);
}