使用正确的类型调用委托

时间:2014-04-03 15:10:03

标签: c# linq

我有一个object类型的参数。可以在该参数上设置任何内容。我需要在该参数中找到具有特定名称的属性。如果它当然存在。

我需要这样的东西(伪代码):

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&lt;&gt;。

我能做些什么来实现这个目标?

先谢谢你们。

这是一个演示:

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不是这里的选项。它太慢了。我试试看。

2 个答案:

答案 0 :(得分:2)

需要考虑两个选项:

  • 使用动态类型调用泛型方法,该方法将返回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();
    }
    

这两个假设您很少进行创建,然后使用相同类型的值多次调用委托。它们可能是也可能不是你所需要的 - 很难用弱的要求来说明。他们确实要求稍后调用函数的值是正确的类型。

答案 1 :(得分:1)

也许这符合您的需求:

Expression.Lambda(Type, Expression, IEnumerable<ParameterExpression>)
          .Compile()
          .DynamicInvoke(...)