开发者

.net define function that takes a lambda expression

开发者 https://www.devze.com 2023-01-29 16:03 出处:网络
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.

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


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


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;
    }


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
}


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

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号