我有一个对象类型的参数。可以在该参数上设置任何内容。我需要在该参数中找到具有特定名称的属性。当然,如果它存在的话。
我需要这样的东西(伪代码):
ParameterExpression arg = Expression.Parameter(parameter.GetType(), "x");
Expression expr = Expression.Property(arg, "Info");
var propertyResolver = Expression.Lambda<Func<parameter.GetType, object>>(expr, arg).Compile();
已经有方法'Expression.Lambda(Type, Expression, ...)
但是这会将System.Delegate返回给我,我需要Func<>。
我能做些什么来实现这一点?
提前感谢伙计们。
这是一个演示:
class Program
{
private Func<object, object> func;
static void Main(string[] args)
{
// lets say in this case the parameter is person but it could be anything
Person parameter = new Person();
ParameterExpression arg = Expression.Parameter(parameter.GetType(), "x");
Expression expr = Expression.Property(arg, "Name");
var func = Expression.Lambda<Func<parameter.GetType, object>>(expr, arg).Compile();
}
}
class Person
{
public string Name { get; set; }
}
创建函数后,我必须在另一个方法的 for 循环中调用它至少 1000 次,因此 DynamicInvoke 在这里不是一个选项。它太慢了。我试了试。
要考虑的两个选项:
-
使用动态类型调用泛型方法,该方法将返回一个
Func<object, object>
,稍后可以通过包装表达式树编译的委托来使用该:public Func<Object, Object> CreateFunc(object sampleValue) { dynamic dynamicValue = sampleValue; return CreateFuncImpl(dynamicValue); // Dynamic type inference } private Func<Object, Object> CreateFuncImpl<T>(T sampleValue) { // You could use Delegate.CreateDelegate as another option - // you don't need expression trees here var parameter = Expression.Parameter(parameter.GetType(), "x"); var expression = Expression.Property(arg, "Name"); var func = Expression.Lambda<Func<T, object>>(expression, parameter) .Compile(); return (object actualValue) => func((T) actualValue); }
-
将属性表达式包装在表达式树中的转换表达式中:
public Func<Object, Object> CreateFunc(object sampleValue) { var parameter = Expression.Parameter(typeof(object), "x"); var conversion = Expression.Convert(parameter, sampleValue.GetType()); var property = Expression.Property(conversion, "Name"); return Expression.Lambda<Func<object, object>>(property, parameter) .Compile(); }
这两种情况都假定您很少执行创建,然后使用相同类型的值多次调用委托。它们可能是您所需要的,也可能不是您需要的 - 很难用弱要求来判断。当然,它们确实要求您稍后调用函数的值属于正确的类型。
也许这将满足您的需求:
Expression.Lambda(Type, Expression, IEnumerable<ParameterExpression>)
.Compile()
.DynamicInvoke(...)