【问题标题】:Creating an Expression<Func<T, object>> variable by reflection通过反射创建 Expression<Func<T, object>> 变量
【发布时间】:2012-08-25 09:22:35
【问题描述】:

我创建了以下类:

public class Person
{
     public string FirstName { get; set; }
     public string LastName { get; set; }
}

我可以将以下语句设置为方法参数:

myClass.SetFieldName<Person>(p => p.LastName);

参数的类型是:

Expression<Func<Person, object>>

现在我要完成的是为通过反射找到的属性调用 SetFieldName 方法。想象一下,我有一个 PropertyInfo 实例(对于 Person.LastName)。我尝试使用其 Lambda 方法创建表达式,但失败了。

如果你能帮我解决这个问题,那就太好了。

问候, 高丽

【问题讨论】:

    标签: c# reflection lambda


    【解决方案1】:

    你只需要稍微扩展一下弗莱姆的答案:

    using System;
    using System.Linq.Expressions;
    using NUnit.Framework;
    
    public class Person
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }
    
    public static class ExpressionBuilder
    {
        public static Expression<Func<TClass, TProperty>> Build<TClass, TProperty>(string fieldName)
        {
            var param = Expression.Parameter(typeof(TClass));
            var field = Expression.PropertyOrField(param, fieldName);
            return Expression.Lambda<Func<TClass, TProperty>>(field, param);
        }
    }
    
    [TestFixture]
    public class Test
    {
        [Test]
        public void TestExpressionBuilder()
        {
            var person = new Person { FirstName = "firstName", LastName = "lastName" };
            var expression = ExpressionBuilder.Build<Person, string>("FirstName");
    
            var firstName = expression.Compile()(person);
    
            Assert.That(firstName, Is.EqualTo(person.FirstName));
        }
    }
    

    【讨论】:

    • 据我所知,上述 Build() 方法仅适用于 TClass 对象的顶级属性。如果您尝试传递子属性表达式,PropertyOrField 调用将失败。它不处理行走对象路径。例如,如果您有一个 Address 对象,而 Person 类有一个 Address 类型的属性“PrimaryAddress”,则不能传入“PrimaryAddress.PostalCode”。
    【解决方案2】:
    // reflected field name
    string fieldName = "LastName";
    
    // create the parameter of the expression (Person)
    ParameterExpression param = Expression.Parameter(typeof(Person), string.Empty);
    
    // create the expression as a get accessor of a particular 
    // field of the parameter (p.LastName)
    Expression field = Expression.PropertyOrField(param, fieldName);
    

    【讨论】:

    • 您好,我需要将创建的表达式作为参数传递给 SetFieldName 方法。但是你创建的 Expression 是 Expression 类型的,它与 Expression> 不兼容。
    【解决方案3】:
    public static class LambdaExpressionExtensions
    {
        public static Expression<Func<TInput, object>> ToUntypedPropertyExpression<TInput, TOutput> (this Expression<Func<TInput, TOutput>> expression)
        {
            var memberName = ((MemberExpression)expression.Body).Member.Name;
    
            var param = Expression.Parameter(typeof(TInput));
            var field = Expression.Property(param, memberName);
            return Expression.Lambda<Func<TInput, object>>(field, param);
        }
    }
    

    【讨论】:

    • 问题是如何从通过反射找到的PropertyInfo 创建Expression&lt;Func&lt;TInput, TOutput&gt;&gt; expression(您将其作为参数接受,因此将其视为黑盒子)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-29
    相关资源
    最近更新 更多