C# 如何用参数序列化方法调用表达式?

C# 如何用参数序列化方法调用表达式?,c#,json,reflection,expression-trees,C#,Json,Reflection,Expression Trees,我有一个远程服务呼叫,描述如下: var user = new User { Name = "check" }; WcfService<IMyService>.Call(s => s.MyMethod(1, "param", user, new Entity { ID = 2 })); var args = mce.Arguments.Select(ExpressionEvaluator.Evaluate).ToArray(); 我知道如何获取接口和方法名称,但无法获取非常

我有一个远程服务呼叫,描述如下:

var user = new User { Name = "check" };
WcfService<IMyService>.Call(s => s.MyMethod(1, "param", user, new Entity { ID = 2 }));
var args = mce.Arguments.Select(ExpressionEvaluator.Evaluate).ToArray();
我知道如何获取接口和方法名称,但无法获取非常量值:

public static class WcfService<TInterface>
{
    public static void Call(Expression<Action<TInterface>> expr)
    {
        var mce = (MethodCallExpression)expr.Body;

        string interfaceName = typeof(TInterface).Name;
        string methodName = mce.Method.Name;

        var args = mce.Arguments
            .Cast<ConstantExpression>()
            .Select(e => e.Value)
            .ToArray();
    }
}
公共静态类WcfService
{

公共静态无效调用(表达式不合适,因为我不想编译表达式并执行它-我只需要计算参数。

A
FieldExpression
有一个
成员(字段)和一个
表达式
,在本例中是一个
常量表达式
,它保存包含该字段的对象。在这里,该常量表达式的
是一个匿名对象,它捕获本地
用户
变量。将
成员
强制转换为
字段信息
可以调用
获取值
在它上面,通过传递该常量表达式的
,您将得到您正在查找的
用户
对象

NewExpression
具有
构造函数
参数
属性(表达式列表),但没有值,因为只有在实际调用该函数时才会生成新对象。您可以编译该表达式,调用它并序列化结果,也可以序列化构造函数调用本身-类似于序列化该服务调用的方式


请注意,
{“Name”:“check”}
{“ID”:2}
缺少类型信息。

A
FieldExpression
有一个
成员(字段)和一个
表达式
,在本例中是一个
常量表达式
,它保存包含该字段的对象。在这里,该常量表达式的
是一个匿名对象,它捕获本地
用户
变量。将
成员
强制转换为
字段信息
可以调用
获取值
在它上面,通过传递该常量表达式的
,您将得到您正在查找的
用户
对象

NewExpression
具有
构造函数
参数
属性(表达式列表),但没有值,因为只有在实际调用该函数时才会生成新对象。您可以编译该表达式,调用它并序列化结果,也可以序列化构造函数调用本身-类似于序列化该服务调用的方式


请注意,
{“Name”:“check”}
{“ID”:2}
缺少类型信息。

我将来自和Pieter Witvoet的答案的信息组合在一起,并收到以下函数:

public static object Evaluate(Expression expr)
{
    switch (expr.NodeType)
    {
        case ExpressionType.Constant:
            return ((ConstantExpression)expr).Value;
        case ExpressionType.MemberAccess:
            var me = (MemberExpression)expr;
            object target = Evaluate(me.Expression);
            switch (me.Member.MemberType)
            {
                case MemberTypes.Field:
                    return ((FieldInfo)me.Member).GetValue(target);
                case MemberTypes.Property:
                    return ((PropertyInfo)me.Member).GetValue(target, null);
                default:
                    throw new NotSupportedException(me.Member.MemberType.ToString());
            }
        case ExpressionType.New:
            return ((NewExpression)expr).Constructor
                .Invoke(((NewExpression)expr).Arguments.Select(Evaluate).ToArray());
        default:
            throw new NotSupportedException(expr.NodeType.ToString());
    }
}
现在,我可以简单地执行以下操作:

var user = new User { Name = "check" };
WcfService<IMyService>.Call(s => s.MyMethod(1, "param", user, new Entity { ID = 2 }));
var args = mce.Arguments.Select(ExpressionEvaluator.Evaluate).ToArray();

我已将来自和Pieter Witvoet的答案的信息结合起来,并收到以下功能:

public static object Evaluate(Expression expr)
{
    switch (expr.NodeType)
    {
        case ExpressionType.Constant:
            return ((ConstantExpression)expr).Value;
        case ExpressionType.MemberAccess:
            var me = (MemberExpression)expr;
            object target = Evaluate(me.Expression);
            switch (me.Member.MemberType)
            {
                case MemberTypes.Field:
                    return ((FieldInfo)me.Member).GetValue(target);
                case MemberTypes.Property:
                    return ((PropertyInfo)me.Member).GetValue(target, null);
                default:
                    throw new NotSupportedException(me.Member.MemberType.ToString());
            }
        case ExpressionType.New:
            return ((NewExpression)expr).Constructor
                .Invoke(((NewExpression)expr).Arguments.Select(Evaluate).ToArray());
        default:
            throw new NotSupportedException(expr.NodeType.ToString());
    }
}
现在,我可以简单地执行以下操作:

var user = new User { Name = "check" };
WcfService<IMyService>.Call(s => s.MyMethod(1, "param", user, new Entity { ID = 2 }));
var args = mce.Arguments.Select(ExpressionEvaluator.Evaluate).ToArray();

可能的重复项无法获取非常量值,因为它们可以链接到闭包或方法调用参数,并且它们将在表达式执行期间进行计算。因此,如果不了解它们,就很难获取它们的实际值可能的重复项无法获取非常量值,因为它们可以链接到闭包或方法调用参数d调用参数,它们将在表达式执行期间进行计算。因此,如果不了解它们,将很难获取它们的实际值。可以的是,类型信息缺失,因为我将使用反射并根据服务方法参数的类型反序列化它们。非常感谢您的帮助。我有您的答案这是另一个,现在一切都正常了。@YeldarKurmangaliyev:关于类型信息,我假设您不打算支持这些参数类型的子类化?类型信息丢失是可以的,因为我将使用反射并根据服务方法参数的类型反序列化它们。非常感谢您的帮助。我已经用另一个答案回答,现在一切都正常了。@YeldarKurmangaliyev:关于类型信息,我想你不打算支持这些参数类型的子类化?