简体   繁体   中英

Using expressions to get intellisense support in C#

I'm trying use expressions in order to have strong typing over properties.

So I have this model.

public class Entity
{
    public int Id { get; set; }
    public string Name { get; set; }
}

And this method which should, well in the end I would like to use the properties in some way but for now I just want to return them.

public List<string> DoSomething<TEntity>(params Expression<Func<TEntity, object>>[] expressions)
{  
        List<string> props = new List<string>();

        foreach (var expression in expressions)
        {
            var memberExpression = expression.Body as MemberExpression;

            var q = memberExpression.Member.Name;

            props.Add(q);
        }
        return props;
}

This is the usage

var props = DoSomething<Entity>(x => x.Id, x => x.Name);

Well, It works but only partially. What I mean by that is that it will work for reference types, for example it will work for Name property because it is a reference type, but it will return null for any value type, in this case for ID which is an int.

Why is that and what is the solution?

Expression<Func<TEntity, object>> is an Expression that builds a Func which returns an object (which is a reference type). If you pass x => x.Id as value of that Expression, the return type of the resulting Func will not match, as int is a value type but the Func is expected to return a reference type.

C#'s compiler will see that and automatically build a Func that wraps the int inside an object (called boxing). But that Func no longer has a simple MemberExpression as its body, because the MemberExpression has to be wrapped in a "boxing expression".

That's basically what happens. So you have to handle the case where expression.Body is not of type MemberExpression to fix that.

This is untested, but it might help:

if (!(expression.Body is MemberExpression))
{
    if (expression.Body is UnaryExpression unaryExpression && unaryExpression.NodeType == ExpressionType.TypeAs)
        expression = unaryExpression.Operand as MemberExpression;
    else
        expression = null;
    if (expression == null)
        throw new ArgumentException("something happened");
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM