.net 定义采用 lambda 表达式的函数

发布于 2024-10-07 03:31:16 字数 650 浏览 3 评论 0原文

我想定义一个像 MVC 扩展模板函数 TextBoxFor 这样的函数,

该函数的有趣之处在于我不必指定 TProperty 类型。 我如何在我的函数定义中设置它。

我的代码如下所示:

public class Helper<TItem>
{
    public string GetMemberName(Expression<Func<TItem, TProperty>> expression)
    {
        ... returns TProperty.Name

    }
}

实际问题是这无法编译...因为它找不到 TProperty 类型。

我想要的结果是使用类型定义一次类...然后使用函数 GetMemberName 来获取每个成员的名称,就像在 MVC 框架中一样。

Helper<Employee> h = new Helper<Employee>();
string name = h.GetMemberName(e=>e.Name);
....

我不想在编写代码时被迫指定 TProperty 类型。基本上它可以是任何对象。

谢谢,

拉杜

I want to define a function like the MVC extension template function TextBoxFor

The interesting thing for that function is that I don't have to specify a TProperty type.
How can I set that in my function definition.

My code look like:

public class Helper<TItem>
{
    public string GetMemberName(Expression<Func<TItem, TProperty>> expression)
    {
        ... returns TProperty.Name

    }
}

The actual problem is that this does not compile ... because it cannot find the TProperty type.

The result I want is to define the class once with a type ... and then use the function GetMemberName to get the name of each member like in MVC framework.

Helper<Employee> h = new Helper<Employee>();
string name = h.GetMemberName(e=>e.Name);
....

I don't want to be forced to specify the TProperty type when I write the code. Basically it can be any object.

Thanks,

Radu

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

天气好吗我好吗 2024-10-14 03:31:17

我曾经写过这个函数,但我记不清了。
但首先将委托签名更改为此 Func,然后对于简单数据类型,获取表达式主体并将其转换为 MemberExpression 并获取第一个参数的名称

如果访问的成员是复杂的成员,则必须将表达式主体转换为 UnaryExpression,获取第一个参数并将其转换为 MemberExpression 并执行第一步中所做的操作。

在调试函数时使用 QuickWatch 可能会找到解决方案。
值得一提的是,阅读 MVC 代码中的 HtmlHelper 可能会有所帮助。

编辑:
粗略记住

更好的方法是将此函数编写为扩展方法(如果需要,可以在适用的情况下对类型进行约束),以便不再需要提供 Employee 类型,因为它是从使用中推断出来的。

所以你的功能是这样的:

public static class Helper
{
    public static string Item<TItem,TMember>(this TItem obj, Expression<Func<TItem, TMember>> expression)
    {
        if (expression.Body is MemberExpression)
        {
            return ((MemberExpression)(expression.Body)).Member.Name;
        }
        if(expression.Body is UnaryExpression)
        {
            return ((MemberExpression)((UnaryExpression)(expression.Body)).Operand).Member.Name;
        }
        throw new InvalidOperationException();
    }
}

所以你的代码会更干净

Employee emp = new Employee();
emp.Item(o=>o.Name);

希望对你有帮助

I wrote this function once but i can't remember it exactly.
But first change the delegate signature to this Func<T, object>, then for simple data types get the expression body and cast it to MemberExpression and get the name of first parameter

if the accessed member is a complex one you must cast the expression body to UnaryExpression the take the first parameter and cast it to MemberExpression and do what you did in first step.

Playing with QuickWatch when debugging the function could lead you to the solution.
Worth to mention that reading the HtmlHelper's in MVC code could be helpful.

EDIT:
Roughly remembered

The better approach is to write this function as Extension Method(with constraint on type where applicable if you want) so that providing Employee type is also not needed anymore, cause it's inferred from usage.

So your function is like that:

public static class Helper
{
    public static string Item<TItem,TMember>(this TItem obj, Expression<Func<TItem, TMember>> expression)
    {
        if (expression.Body is MemberExpression)
        {
            return ((MemberExpression)(expression.Body)).Member.Name;
        }
        if(expression.Body is UnaryExpression)
        {
            return ((MemberExpression)((UnaryExpression)(expression.Body)).Operand).Member.Name;
        }
        throw new InvalidOperationException();
    }
}

So your code will be much cleaner

Employee emp = new Employee();
emp.Item(o=>o.Name);

Hope to helps you

爱你不解释 2024-10-14 03:31:16

这就是您所需要的:

public class Helper<TItem>
{
    public string GetMemberName<TProperty>(Expression<Func<TItem, TProperty>> expression)
    {
        return string.Empty; // I didn't implement it
    }
}

只需将 附加到您的方法名称即可使其通用。而TProperty的类型可以从提供的表达式中推断出来,所以使用时不需要指定它的类型,可以简单地:

Helper<Employee> h = new Helper<Employee>();
h.GetMemberName( e=>e.Name); //if Employee has such a property

This is what you need:

public class Helper<TItem>
{
    public string GetMemberName<TProperty>(Expression<Func<TItem, TProperty>> expression)
    {
        return string.Empty; // I didn't implement it
    }
}

Just append <TProperty> to your method name to make it generic. And the type of TProperty can be inferred from provided expression, so you needn't to specify its type when using, can be simply:

Helper<Employee> h = new Helper<Employee>();
h.GetMemberName( e=>e.Name); //if Employee has such a property
_畞蕅 2024-10-14 03:31:16

以下函数返回使用 lambda 表达式传递给它的任何属性的名称:

    public static string Property<T>(Expression<Func<T>> e)
    {
        var member = (MemberExpression)e.Body;
        return member.Member.Name;
    }

Following function returns any property's name that is passed to it using a lambda expression:

    public static string Property<T>(Expression<Func<T>> e)
    {
        var member = (MemberExpression)e.Body;
        return member.Member.Name;
    }
蓝眼泪 2024-10-14 03:31:16

您可以使用 ModelMetaData 类从 Expression 中提取信息。

public string GetMemberName<TProperty>(Expression<Func<TItem, TProperty>> expression) {
   var meta = ModelMetaData.FromLambdaExpression(expression, null);
   return meta.PropertyName; // Or something else
}

You can use the ModelMetaData class to extract information from the Expression.

public string GetMemberName<TProperty>(Expression<Func<TItem, TProperty>> expression) {
   var meta = ModelMetaData.FromLambdaExpression(expression, null);
   return meta.PropertyName; // Or something else
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文