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
{
公共静态无效调用(表达式不合适,因为我不想编译表达式并执行它-我只需要计算参数。AFieldExpression
有一个成员(字段)和一个表达式
,在本例中是一个常量表达式
,它保存包含该字段的对象。在这里,该常量表达式的值
是一个匿名对象,它捕获本地用户
变量。将成员
强制转换为字段信息
可以调用获取值
在它上面,通过传递该常量表达式的值
,您将得到您正在查找的用户
对象
NewExpression
具有构造函数
和参数
属性(表达式列表),但没有值,因为只有在实际调用该函数时才会生成新对象。您可以编译该表达式,调用它并序列化结果,也可以序列化构造函数调用本身-类似于序列化该服务调用的方式
请注意,{“Name”:“check”}
和{“ID”:2}
缺少类型信息。AFieldExpression
有一个成员(字段)和一个表达式
,在本例中是一个常量表达式
,它保存包含该字段的对象。在这里,该常量表达式的值
是一个匿名对象,它捕获本地用户
变量。将成员
强制转换为字段信息
可以调用获取值
在它上面,通过传递该常量表达式的值
,您将得到您正在查找的用户
对象
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:关于类型信息,我想你不打算支持这些参数类型的子类化?