如何获取lambda表达式的值

时间:2015-12-02 05:34:56

标签: c# lambda

我对这个很难过。

我正在开发一个HTML扩展方法,它以lambda表达式的形式接受int值。

我试图在一个简单的c#应用程序中尽可能地模仿它。我无法以所需的lambda表达式的格式调用我的扩展方法。这个扩展方法是对一些Telerik控件的支持,我正试图在我们部门的控件中定义一些标准。 (我仍然没有弄清楚如何int价值lol)。

我试图记录它并尽可能地命名特定的代码片段!

class Program
{
    static void Main(string[] args)
    {
        var db = new CustomerDatabase<MyCustomers>();
        db.Customers.Add(new MyCustomers { Id = 1, Name = "Gandalf the Grey" });
        db.Customers.Add(new MyCustomers { Id = 2, Name = "Bilbo Baggins" }); 
        //Was watching Fellowship of the Ring while doing this lol

        //This foreach is similar to the foreach that would be 
        //in my MVC view where db.Customers is really my ViewModel
        foreach (var item in db.Customers)
        {
            //This is where my trouble begins... :(
            Helpers.WriteIdToConsole(item, item.Id);
            Helpers.WriteIdToConsole(item => );
        }
    }

    /// <summary>
    /// CLASS #1
    /// Serves as a holding container for records
    /// </summary>
    /// <typeparam name="TModel"></typeparam>
    public class CustomerDatabase<TModel>
        where TModel : class
    {
        public List<TModel> Customers { get;set; }
    }

    /// <summary>
    /// CLASS #2
    /// Simple 'model' class in an MVC View
    /// </summary>
    public class MyCustomers
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

    /// <summary>
    /// CLASS #3
    /// Replicates a custom HtmlExtension class I'm developing
    /// </summary>
    public static class Helpers
    {
        /// <summary>
        /// Method #A
        /// One of the methods I'm working on
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="expression"></param>
        public static void WriteIdToConsole<T>(Expression<Func<T, int>> expression)
            where T : class 
        {
            var id = 999;
            Console.WriteLine($"Id: {id}");
        }
    }
}

更新#1

以下是我在Razor View中访问的内容。方法cols.NavigationButton是我正在尝试构建的扩展方法。如果按照下面的Kirill Shlenskiy的建议答案保留,我必须创建一个Event类型或TObj类的新实例。

@model List<Event>

@(Html.Kendo().Grid<Event>()
      .Name("pagingGrid")
      .Columns(cols =>
      {
          cols.NavigationButton("Edit", "Edit", "Event",new Event(), p => p.Id);
          cols.Bound(p => p.Name);
      })
      .StandardPagingGrid("Event", "Administration")
)

2 个答案:

答案 0 :(得分:2)

您需要将Expression传递给方法,并且还需要明确指定type参数。

您可以使用/调用该方法(WriteIdToConsole),如下所示

foreach (var item in db.Customers)
{
    Helpers.WriteIdToConsole<MyCustomers>(myCustomer => myCustomer.Id);
}

Here是完整代码审核的点网小提琴。

答案 1 :(得分:2)

在你的问题中,你说你还在搞清楚&#34;如何获得int值&#34;所以我假设你是在一个更通用的实现之后可以为您提供正在访问的成员的名称​​和其值。这是给你的一个片段:

public static void WriteToConsole<TObj, TMember>(TObj obj, Expression<Func<TObj, TMember>> expression)
{
    MemberExpression memberExpr = (MemberExpression)expression.Body;
    string memberName = memberExpr.Member.Name;
    Func<TObj, TMember> compiledDelegate = expression.Compile();
    TMember value = compiledDelegate(obj);

    Console.WriteLine($"{memberName}: {value}");
}

用法:

var dummy = new Dummy { ID = 123 };

WriteToConsole(dummy, d => d.ID); // Outputs "ID: 123"

我删除了通用引用类型约束(where T : class),因为它也可以在值类型上正常工作。

需要注意的一点是,为了提取值,您不仅需要能够执行此操作的表达式,还需要将一个实例传递给从表达式编译的委托(因此您在第一个轨道上正确Helpers.WriteIdToConsole调用你的代码 - 你只需要将它带到终点线。)

修改

如果您只关心从表达式中提取基本成员信息,则可以使用稍微不同的方法:

public static MemberInfo Member<T>(Expression<Func<T, object>> expr)
{
    // This is a tricky case because of the "object" return type.
    // Providing an expression which has a value return type will
    // result in a UnaryExpression body, whereas an expression which
    // has a reference return type will have a MemberExpression Body.
    UnaryExpression unaryExpr = expr.Body as UnaryExpression;
    MemberExpression memberExpr = (MemberExpression)(unaryExpr == null ? expr.Body : unaryExpr.Operand);

    return memberExpr.Member;
}

基本用法:

MemberInfo id = Member<MyCustomers>(item => item.Id);

Console.WriteLine(id.Name); // Outputs "Id"

你插入它的方式:

public static void NavigationButton<T>(string ..., string ..., string ..., Expression<Func<T, object>> expression)
{
    MemberInfo member = Member(expression);

    // Do something with member, cast to PropertyInfo if needed etc.
}

...

NavigationButton<MyCustomers>("Edit", "Edit", "Event", p => p.Id);